• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * (C) 1999 Lars Knoll (knoll@kde.org)
3  * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
4  * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
5  * (C) 2001 Peter Kelly (pmk@post.com)
6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "config.h"
25 #include "Range.h"
26 #include "RangeException.h"
27 
28 #include "CString.h"
29 #include "ClientRect.h"
30 #include "ClientRectList.h"
31 #include "DocumentFragment.h"
32 #include "FrameView.h"
33 #include "HTMLElement.h"
34 #include "NodeWithIndex.h"
35 #include "ProcessingInstruction.h"
36 #include "Text.h"
37 #include "TextIterator.h"
38 #include "VisiblePosition.h"
39 #include "htmlediting.h"
40 #include "markup.h"
41 #include "visible_units.h"
42 #include <stdio.h>
43 #include <wtf/RefCountedLeakCounter.h>
44 
45 namespace WebCore {
46 
47 using namespace std;
48 
49 #ifndef NDEBUG
50 static WTF::RefCountedLeakCounter rangeCounter("Range");
51 #endif
52 
Range(PassRefPtr<Document> ownerDocument)53 inline Range::Range(PassRefPtr<Document> ownerDocument)
54     : m_ownerDocument(ownerDocument)
55     , m_start(m_ownerDocument)
56     , m_end(m_ownerDocument)
57 {
58 #ifndef NDEBUG
59     rangeCounter.increment();
60 #endif
61 
62     m_ownerDocument->attachRange(this);
63 }
64 
create(PassRefPtr<Document> ownerDocument)65 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument)
66 {
67     return adoptRef(new Range(ownerDocument));
68 }
69 
Range(PassRefPtr<Document> ownerDocument,PassRefPtr<Node> startContainer,int startOffset,PassRefPtr<Node> endContainer,int endOffset)70 inline Range::Range(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
71     : m_ownerDocument(ownerDocument)
72     , m_start(m_ownerDocument)
73     , m_end(m_ownerDocument)
74 {
75 #ifndef NDEBUG
76     rangeCounter.increment();
77 #endif
78 
79     m_ownerDocument->attachRange(this);
80 
81     // Simply setting the containers and offsets directly would not do any of the checking
82     // that setStart and setEnd do, so we call those functions.
83     ExceptionCode ec = 0;
84     setStart(startContainer, startOffset, ec);
85     ASSERT(!ec);
86     setEnd(endContainer, endOffset, ec);
87     ASSERT(!ec);
88 }
89 
create(PassRefPtr<Document> ownerDocument,PassRefPtr<Node> startContainer,int startOffset,PassRefPtr<Node> endContainer,int endOffset)90 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
91 {
92     return adoptRef(new Range(ownerDocument, startContainer, startOffset, endContainer, endOffset));
93 }
94 
create(PassRefPtr<Document> ownerDocument,const Position & start,const Position & end)95 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end)
96 {
97     // FIXME: we shouldn't be using deprecatedEditingOffset here
98     return adoptRef(new Range(ownerDocument, start.node(), start.deprecatedEditingOffset(), end.node(), end.deprecatedEditingOffset()));
99 }
100 
~Range()101 Range::~Range()
102 {
103     // Always detach (even if we've already detached) to fix https://bugs.webkit.org/show_bug.cgi?id=26044
104     m_ownerDocument->detachRange(this);
105 
106 #ifndef NDEBUG
107     rangeCounter.decrement();
108 #endif
109 }
110 
startContainer(ExceptionCode & ec) const111 Node* Range::startContainer(ExceptionCode& ec) const
112 {
113     if (!m_start.container()) {
114         ec = INVALID_STATE_ERR;
115         return 0;
116     }
117 
118     return m_start.container();
119 }
120 
startOffset(ExceptionCode & ec) const121 int Range::startOffset(ExceptionCode& ec) const
122 {
123     if (!m_start.container()) {
124         ec = INVALID_STATE_ERR;
125         return 0;
126     }
127 
128     return m_start.offset();
129 }
130 
endContainer(ExceptionCode & ec) const131 Node* Range::endContainer(ExceptionCode& ec) const
132 {
133     if (!m_start.container()) {
134         ec = INVALID_STATE_ERR;
135         return 0;
136     }
137 
138     return m_end.container();
139 }
140 
endOffset(ExceptionCode & ec) const141 int Range::endOffset(ExceptionCode& ec) const
142 {
143     if (!m_start.container()) {
144         ec = INVALID_STATE_ERR;
145         return 0;
146     }
147 
148     return m_end.offset();
149 }
150 
commonAncestorContainer(ExceptionCode & ec) const151 Node* Range::commonAncestorContainer(ExceptionCode& ec) const
152 {
153     if (!m_start.container()) {
154         ec = INVALID_STATE_ERR;
155         return 0;
156     }
157 
158     return commonAncestorContainer(m_start.container(), m_end.container());
159 }
160 
commonAncestorContainer(Node * containerA,Node * containerB)161 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
162 {
163     for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
164         for (Node* parentB = containerB; parentB; parentB = parentB->parentNode()) {
165             if (parentA == parentB)
166                 return parentA;
167         }
168     }
169     return 0;
170 }
171 
collapsed(ExceptionCode & ec) const172 bool Range::collapsed(ExceptionCode& ec) const
173 {
174     if (!m_start.container()) {
175         ec = INVALID_STATE_ERR;
176         return 0;
177     }
178 
179     return m_start == m_end;
180 }
181 
setStart(PassRefPtr<Node> refNode,int offset,ExceptionCode & ec)182 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
183 {
184     if (!m_start.container()) {
185         ec = INVALID_STATE_ERR;
186         return;
187     }
188 
189     if (!refNode) {
190         ec = NOT_FOUND_ERR;
191         return;
192     }
193 
194     if (refNode->document() != m_ownerDocument) {
195         ec = WRONG_DOCUMENT_ERR;
196         return;
197     }
198 
199     ec = 0;
200     Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
201     if (ec)
202         return;
203 
204     m_start.set(refNode, offset, childNode);
205 
206     // check if different root container
207     Node* endRootContainer = m_end.container();
208     while (endRootContainer->parentNode())
209         endRootContainer = endRootContainer->parentNode();
210     Node* startRootContainer = m_start.container();
211     while (startRootContainer->parentNode())
212         startRootContainer = startRootContainer->parentNode();
213     if (startRootContainer != endRootContainer)
214         collapse(true, ec);
215     // check if new start after end
216     else if (compareBoundaryPoints(m_start, m_end) > 0)
217         collapse(true, ec);
218 }
219 
setEnd(PassRefPtr<Node> refNode,int offset,ExceptionCode & ec)220 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
221 {
222     if (!m_start.container()) {
223         ec = INVALID_STATE_ERR;
224         return;
225     }
226 
227     if (!refNode) {
228         ec = NOT_FOUND_ERR;
229         return;
230     }
231 
232     if (refNode->document() != m_ownerDocument) {
233         ec = WRONG_DOCUMENT_ERR;
234         return;
235     }
236 
237     ec = 0;
238     Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
239     if (ec)
240         return;
241 
242     m_end.set(refNode, offset, childNode);
243 
244     // check if different root container
245     Node* endRootContainer = m_end.container();
246     while (endRootContainer->parentNode())
247         endRootContainer = endRootContainer->parentNode();
248     Node* startRootContainer = m_start.container();
249     while (startRootContainer->parentNode())
250         startRootContainer = startRootContainer->parentNode();
251     if (startRootContainer != endRootContainer)
252         collapse(false, ec);
253     // check if new end before start
254     if (compareBoundaryPoints(m_start, m_end) > 0)
255         collapse(false, ec);
256 }
257 
collapse(bool toStart,ExceptionCode & ec)258 void Range::collapse(bool toStart, ExceptionCode& ec)
259 {
260     if (!m_start.container()) {
261         ec = INVALID_STATE_ERR;
262         return;
263     }
264 
265     if (toStart)
266         m_end = m_start;
267     else
268         m_start = m_end;
269 }
270 
isPointInRange(Node * refNode,int offset,ExceptionCode & ec)271 bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec)
272 {
273     if (!m_start.container()) {
274         ec = INVALID_STATE_ERR;
275         return false;
276     }
277 
278     if (!refNode) {
279         ec = HIERARCHY_REQUEST_ERR;
280         return false;
281     }
282 
283     if (!refNode->attached()) {
284         // Firefox doesn't throw an exception for this case; it returns false.
285         return false;
286     }
287 
288     if (refNode->document() != m_ownerDocument) {
289         ec = WRONG_DOCUMENT_ERR;
290         return false;
291     }
292 
293     ec = 0;
294     checkNodeWOffset(refNode, offset, ec);
295     if (ec)
296         return false;
297 
298     return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset()) >= 0
299         && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()) <= 0;
300 }
301 
comparePoint(Node * refNode,int offset,ExceptionCode & ec) const302 short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) const
303 {
304     // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
305     // This method returns -1, 0 or 1 depending on if the point described by the
306     // refNode node and an offset within the node is before, same as, or after the range respectively.
307 
308     if (!m_start.container()) {
309         ec = INVALID_STATE_ERR;
310         return 0;
311     }
312 
313     if (!refNode) {
314         ec = HIERARCHY_REQUEST_ERR;
315         return 0;
316     }
317 
318     if (!refNode->attached() || refNode->document() != m_ownerDocument) {
319         ec = WRONG_DOCUMENT_ERR;
320         return 0;
321     }
322 
323     ec = 0;
324     checkNodeWOffset(refNode, offset, ec);
325     if (ec)
326         return 0;
327 
328     // compare to start, and point comes before
329     if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset()) < 0)
330         return -1;
331 
332     // compare to end, and point comes after
333     if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()) > 0)
334         return 1;
335 
336     // point is in the middle of this range, or on the boundary points
337     return 0;
338 }
339 
compareNode(Node * refNode,ExceptionCode & ec) const340 Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) const
341 {
342     // http://developer.mozilla.org/en/docs/DOM:range.compareNode
343     // This method returns 0, 1, 2, or 3 based on if the node is before, after,
344     // before and after(surrounds), or inside the range, respectively
345 
346     if (!refNode) {
347         ec = NOT_FOUND_ERR;
348         return NODE_BEFORE;
349     }
350 
351     if (!m_start.container() && refNode->attached()) {
352         ec = INVALID_STATE_ERR;
353         return NODE_BEFORE;
354     }
355 
356     if (m_start.container() && !refNode->attached()) {
357         // Firefox doesn't throw an exception for this case; it returns 0.
358         return NODE_BEFORE;
359     }
360 
361     if (refNode->document() != m_ownerDocument) {
362         // Firefox doesn't throw an exception for this case; it returns 0.
363         return NODE_BEFORE;
364     }
365 
366     Node* parentNode = refNode->parentNode();
367     int nodeIndex = refNode->nodeIndex();
368 
369     if (!parentNode) {
370         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
371         // but we throw to match firefox behavior
372         ec = NOT_FOUND_ERR;
373         return NODE_BEFORE;
374     }
375 
376     if (comparePoint(parentNode, nodeIndex, ec) < 0) { // starts before
377         if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
378             return NODE_BEFORE_AND_AFTER;
379         return NODE_BEFORE; // ends before or in the range
380     } else { // starts at or after the range start
381         if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
382             return NODE_AFTER;
383         return NODE_INSIDE; // ends inside the range
384     }
385 }
386 
compareBoundaryPoints(CompareHow how,const Range * sourceRange,ExceptionCode & ec) const387 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionCode& ec) const
388 {
389     if (!m_start.container()) {
390         ec = INVALID_STATE_ERR;
391         return 0;
392     }
393 
394     if (!sourceRange) {
395         ec = NOT_FOUND_ERR;
396         return 0;
397     }
398 
399     ec = 0;
400     Node* thisCont = commonAncestorContainer(ec);
401     if (ec)
402         return 0;
403     Node* sourceCont = sourceRange->commonAncestorContainer(ec);
404     if (ec)
405         return 0;
406 
407     if (thisCont->document() != sourceCont->document()) {
408         ec = WRONG_DOCUMENT_ERR;
409         return 0;
410     }
411 
412     Node* thisTop = thisCont;
413     Node* sourceTop = sourceCont;
414     while (thisTop->parentNode())
415         thisTop = thisTop->parentNode();
416     while (sourceTop->parentNode())
417         sourceTop = sourceTop->parentNode();
418     if (thisTop != sourceTop) { // in different DocumentFragments
419         ec = WRONG_DOCUMENT_ERR;
420         return 0;
421     }
422 
423     switch (how) {
424         case START_TO_START:
425             return compareBoundaryPoints(m_start, sourceRange->m_start);
426         case START_TO_END:
427             return compareBoundaryPoints(m_end, sourceRange->m_start);
428         case END_TO_END:
429             return compareBoundaryPoints(m_end, sourceRange->m_end);
430         case END_TO_START:
431             return compareBoundaryPoints(m_start, sourceRange->m_end);
432     }
433 
434     ec = SYNTAX_ERR;
435     return 0;
436 }
437 
compareBoundaryPoints(Node * containerA,int offsetA,Node * containerB,int offsetB)438 short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB)
439 {
440     ASSERT(containerA);
441     ASSERT(containerB);
442 
443     if (!containerA)
444         return -1;
445     if (!containerB)
446         return 1;
447 
448     // see DOM2 traversal & range section 2.5
449 
450     // case 1: both points have the same container
451     if (containerA == containerB) {
452         if (offsetA == offsetB)
453             return 0;           // A is equal to B
454         if (offsetA < offsetB)
455             return -1;          // A is before B
456         else
457             return 1;           // A is after B
458     }
459 
460     // case 2: node C (container B or an ancestor) is a child node of A
461     Node* c = containerB;
462     while (c && c->parentNode() != containerA)
463         c = c->parentNode();
464     if (c) {
465         int offsetC = 0;
466         Node* n = containerA->firstChild();
467         while (n != c && offsetC < offsetA) {
468             offsetC++;
469             n = n->nextSibling();
470         }
471 
472         if (offsetA <= offsetC)
473             return -1;              // A is before B
474         else
475             return 1;               // A is after B
476     }
477 
478     // case 3: node C (container A or an ancestor) is a child node of B
479     c = containerA;
480     while (c && c->parentNode() != containerB)
481         c = c->parentNode();
482     if (c) {
483         int offsetC = 0;
484         Node* n = containerB->firstChild();
485         while (n != c && offsetC < offsetB) {
486             offsetC++;
487             n = n->nextSibling();
488         }
489 
490         if (offsetC < offsetB)
491             return -1;              // A is before B
492         else
493             return 1;               // A is after B
494     }
495 
496     // case 4: containers A & B are siblings, or children of siblings
497     // ### we need to do a traversal here instead
498     Node* commonAncestor = commonAncestorContainer(containerA, containerB);
499     if (!commonAncestor)
500         return 0;
501     Node* childA = containerA;
502     while (childA && childA->parentNode() != commonAncestor)
503         childA = childA->parentNode();
504     if (!childA)
505         childA = commonAncestor;
506     Node* childB = containerB;
507     while (childB && childB->parentNode() != commonAncestor)
508         childB = childB->parentNode();
509     if (!childB)
510         childB = commonAncestor;
511 
512     if (childA == childB)
513         return 0; // A is equal to B
514 
515     Node* n = commonAncestor->firstChild();
516     while (n) {
517         if (n == childA)
518             return -1; // A is before B
519         if (n == childB)
520             return 1; // A is after B
521         n = n->nextSibling();
522     }
523 
524     // Should never reach this point.
525     ASSERT_NOT_REACHED();
526     return 0;
527 }
528 
compareBoundaryPoints(const RangeBoundaryPoint & boundaryA,const RangeBoundaryPoint & boundaryB)529 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB)
530 {
531     return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset());
532 }
533 
boundaryPointsValid() const534 bool Range::boundaryPointsValid() const
535 {
536     return m_start.container() && compareBoundaryPoints(m_start, m_end) <= 0;
537 }
538 
deleteContents(ExceptionCode & ec)539 void Range::deleteContents(ExceptionCode& ec)
540 {
541     checkDeleteExtract(ec);
542     if (ec)
543         return;
544 
545     processContents(DELETE_CONTENTS, ec);
546 }
547 
intersectsNode(Node * refNode,ExceptionCode & ec)548 bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
549 {
550     // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
551     // Returns a bool if the node intersects the range.
552 
553     if (!refNode) {
554         ec = NOT_FOUND_ERR;
555         return false;
556     }
557 
558     if ((!m_start.container() && refNode->attached())
559             || (m_start.container() && !refNode->attached())
560             || refNode->document() != m_ownerDocument) {
561         // Firefox doesn't throw an exception for these cases; it returns false.
562         return false;
563     }
564 
565     Node* parentNode = refNode->parentNode();
566     int nodeIndex = refNode->nodeIndex();
567 
568     if (!parentNode) {
569         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
570         // but we throw to match firefox behavior
571         ec = NOT_FOUND_ERR;
572         return false;
573     }
574 
575     if (comparePoint(parentNode, nodeIndex, ec) < 0 && // starts before start
576         comparePoint(parentNode, nodeIndex + 1, ec) < 0) { // ends before start
577         return false;
578     } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after end
579                comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after end
580         return false;
581     }
582 
583     return true; // all other cases
584 }
585 
processContents(ActionType action,ExceptionCode & ec)586 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
587 {
588     // FIXME: To work properly with mutation events, we will have to take into account
589     // situations where the tree is being transformed while we work on it - ugh!
590 
591     RefPtr<DocumentFragment> fragment;
592     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
593         fragment = DocumentFragment::create(m_ownerDocument.get());
594 
595     ec = 0;
596     if (collapsed(ec))
597         return fragment.release();
598     if (ec)
599         return 0;
600 
601     Node* commonRoot = commonAncestorContainer(ec);
602     if (ec)
603         return 0;
604     ASSERT(commonRoot);
605 
606     // what is the highest node that partially selects the start of the range?
607     Node* partialStart = 0;
608     if (m_start.container() != commonRoot) {
609         partialStart = m_start.container();
610         while (partialStart->parentNode() != commonRoot)
611             partialStart = partialStart->parentNode();
612     }
613 
614     // what is the highest node that partially selects the end of the range?
615     Node* partialEnd = 0;
616     if (m_end.container() != commonRoot) {
617         partialEnd = m_end.container();
618         while (partialEnd->parentNode() != commonRoot)
619             partialEnd = partialEnd->parentNode();
620     }
621 
622     // Simple case: the start and end containers are the same. We just grab
623     // everything >= start offset and < end offset
624     if (m_start.container() == m_end.container()) {
625         Node::NodeType startNodeType = m_start.container()->nodeType();
626         if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {
627             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
628                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));
629                 c->deleteData(m_end.offset(), c->length() - m_end.offset(), ec);
630                 c->deleteData(0, m_start.offset(), ec);
631                 fragment->appendChild(c.release(), ec);
632             }
633             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
634                 static_cast<CharacterData*>(m_start.container())->deleteData(m_start.offset(), m_end.offset() - m_start.offset(), ec);
635         } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
636             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
637                 RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));
638                 c->setData(c->data().substring(m_start.offset(), m_end.offset() - m_start.offset()), ec);
639                 fragment->appendChild(c.release(), ec);
640             }
641             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
642                 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());
643                 String data(pi->data());
644                 data.remove(m_start.offset(), m_end.offset() - m_start.offset());
645                 pi->setData(data, ec);
646             }
647         } else {
648             Node* n = m_start.container()->firstChild();
649             int i;
650             for (i = 0; n && i < m_start.offset(); i++) // skip until start offset
651                 n = n->nextSibling();
652             int endOffset = m_end.offset();
653             while (n && i < endOffset) { // delete until end offset
654                 Node* next = n->nextSibling();
655                 if (action == EXTRACT_CONTENTS)
656                     fragment->appendChild(n, ec); // will remove n from its parent
657                 else if (action == CLONE_CONTENTS)
658                     fragment->appendChild(n->cloneNode(true), ec);
659                 else
660                     m_start.container()->removeChild(n, ec);
661                 n = next;
662                 i++;
663             }
664         }
665         return fragment.release();
666     }
667 
668     // Complex case: Start and end containers are different.
669     // There are three possibilities here:
670     // 1. Start container == commonRoot (End container must be a descendant)
671     // 2. End container == commonRoot (Start container must be a descendant)
672     // 3. Neither is commonRoot, they are both descendants
673     //
674     // In case 3, we grab everything after the start (up until a direct child
675     // of commonRoot) into leftContents, and everything before the end (up until
676     // a direct child of commonRoot) into rightContents. Then we process all
677     // commonRoot children between leftContents and rightContents
678     //
679     // In case 1 or 2, we skip either processing of leftContents or rightContents,
680     // in which case the last lot of nodes either goes from the first or last
681     // child of commonRoot.
682     //
683     // These are deleted, cloned, or extracted (i.e. both) depending on action.
684 
685     RefPtr<Node> leftContents;
686     if (m_start.container() != commonRoot) {
687         // process the left-hand side of the range, up until the last ancestor of
688         // start container before commonRoot
689         Node::NodeType startNodeType = m_start.container()->nodeType();
690         if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {
691             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
692                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));
693                 c->deleteData(0, m_start.offset(), ec);
694                 leftContents = c.release();
695             }
696             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
697                 static_cast<CharacterData*>(m_start.container())->deleteData(
698                     m_start.offset(), static_cast<CharacterData*>(m_start.container())->length() - m_start.offset(), ec);
699         } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
700             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
701                 RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));
702                 c->setData(c->data().substring(m_start.offset()), ec);
703                 leftContents = c.release();
704             }
705             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
706                 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());
707                 String data(pi->data());
708                 pi->setData(data.left(m_start.offset()), ec);
709             }
710         } else {
711             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
712                 leftContents = m_start.container()->cloneNode(false);
713             Node* n = m_start.container()->firstChild();
714             for (int i = 0; n && i < m_start.offset(); i++) // skip until start offset
715                 n = n->nextSibling();
716             while (n) { // process until end
717                 Node* next = n->nextSibling();
718                 if (action == EXTRACT_CONTENTS)
719                     leftContents->appendChild(n, ec); // will remove n from start container
720                 else if (action == CLONE_CONTENTS)
721                     leftContents->appendChild(n->cloneNode(true), ec);
722                 else
723                     m_start.container()->removeChild(n, ec);
724                 n = next;
725             }
726         }
727 
728         Node* leftParent = m_start.container()->parentNode();
729         Node* n = m_start.container()->nextSibling();
730         for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) {
731             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
732                 RefPtr<Node> leftContentsParent = leftParent->cloneNode(false);
733                 leftContentsParent->appendChild(leftContents, ec);
734                 leftContents = leftContentsParent;
735             }
736 
737             Node* next;
738             for (; n; n = next) {
739                 next = n->nextSibling();
740                 if (action == EXTRACT_CONTENTS)
741                     leftContents->appendChild(n, ec); // will remove n from leftParent
742                 else if (action == CLONE_CONTENTS)
743                     leftContents->appendChild(n->cloneNode(true), ec);
744                 else
745                     leftParent->removeChild(n, ec);
746             }
747             n = leftParent->nextSibling();
748         }
749     }
750 
751     RefPtr<Node> rightContents;
752     if (m_end.container() != commonRoot) {
753         // delete the right-hand side of the range, up until the last ancestor of
754         // end container before commonRoot
755         Node::NodeType endNodeType = m_end.container()->nodeType();
756         if (endNodeType == Node::TEXT_NODE || endNodeType == Node::CDATA_SECTION_NODE || endNodeType == Node::COMMENT_NODE) {
757             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
758                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_end.container()->cloneNode(true));
759                 c->deleteData(m_end.offset(), static_cast<CharacterData*>(m_end.container())->length() - m_end.offset(), ec);
760                 rightContents = c;
761             }
762             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
763                 static_cast<CharacterData*>(m_end.container())->deleteData(0, m_end.offset(), ec);
764         } else if (endNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
765             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
766                 RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_end.container()->cloneNode(true));
767                 c->setData(c->data().left(m_end.offset()), ec);
768                 rightContents = c.release();
769             }
770             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
771                 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_end.container());
772                 pi->setData(pi->data().substring(m_end.offset()), ec);
773             }
774         } else {
775             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
776                 rightContents = m_end.container()->cloneNode(false);
777             Node* n = m_end.container()->firstChild();
778             if (n && m_end.offset()) {
779                 for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.offset()
780                     Node* next = n->nextSibling();
781                     if (!next)
782                         break;
783                     n = next;
784                 }
785                 Node* prev;
786                 for (; n; n = prev) {
787                     prev = n->previousSibling();
788                     if (action == EXTRACT_CONTENTS)
789                         rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent
790                     else if (action == CLONE_CONTENTS)
791                         rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec);
792                     else
793                         m_end.container()->removeChild(n, ec);
794                 }
795             }
796         }
797 
798         Node* rightParent = m_end.container()->parentNode();
799         Node* n = m_end.container()->previousSibling();
800         for (; rightParent != commonRoot; rightParent = rightParent->parentNode()) {
801             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
802                 RefPtr<Node> rightContentsParent = rightParent->cloneNode(false);
803                 rightContentsParent->appendChild(rightContents, ec);
804                 rightContents = rightContentsParent;
805             }
806             Node* prev;
807             for (; n; n = prev) {
808                 prev = n->previousSibling();
809                 if (action == EXTRACT_CONTENTS)
810                     rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent
811                 else if (action == CLONE_CONTENTS)
812                     rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec);
813                 else
814                     rightParent->removeChild(n, ec);
815             }
816             n = rightParent->previousSibling();
817         }
818     }
819 
820     // delete all children of commonRoot between the start and end container
821 
822     Node* processStart; // child of commonRoot
823     if (m_start.container() == commonRoot) {
824         processStart = m_start.container()->firstChild();
825         for (int i = 0; i < m_start.offset(); i++)
826             processStart = processStart->nextSibling();
827     } else {
828         processStart = m_start.container();
829         while (processStart->parentNode() != commonRoot)
830             processStart = processStart->parentNode();
831         processStart = processStart->nextSibling();
832     }
833     Node* processEnd; // child of commonRoot
834     if (m_end.container() == commonRoot) {
835         processEnd = m_end.container()->firstChild();
836         for (int i = 0; i < m_end.offset(); i++)
837             processEnd = processEnd->nextSibling();
838     } else {
839         processEnd = m_end.container();
840         while (processEnd->parentNode() != commonRoot)
841             processEnd = processEnd->parentNode();
842     }
843 
844     // Collapse the range, making sure that the result is not within a node that was partially selected.
845     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
846         if (partialStart)
847             setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec);
848         else if (partialEnd)
849             setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec);
850         if (ec)
851             return 0;
852         m_end = m_start;
853     }
854 
855     // Now add leftContents, stuff in between, and rightContents to the fragment
856     // (or just delete the stuff in between)
857 
858     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
859         fragment->appendChild(leftContents, ec);
860 
861     Node* next;
862     Node* n;
863     if (processStart) {
864         for (n = processStart; n && n != processEnd; n = next) {
865             next = n->nextSibling();
866             if (action == EXTRACT_CONTENTS)
867                 fragment->appendChild(n, ec); // will remove from commonRoot
868             else if (action == CLONE_CONTENTS)
869                 fragment->appendChild(n->cloneNode(true), ec);
870             else
871                 commonRoot->removeChild(n, ec);
872         }
873     }
874 
875     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
876         fragment->appendChild(rightContents, ec);
877 
878     return fragment.release();
879 }
880 
extractContents(ExceptionCode & ec)881 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
882 {
883     checkDeleteExtract(ec);
884     if (ec)
885         return 0;
886 
887     return processContents(EXTRACT_CONTENTS, ec);
888 }
889 
cloneContents(ExceptionCode & ec)890 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionCode& ec)
891 {
892     if (!m_start.container()) {
893         ec = INVALID_STATE_ERR;
894         return 0;
895     }
896 
897     return processContents(CLONE_CONTENTS, ec);
898 }
899 
insertNode(PassRefPtr<Node> prpNewNode,ExceptionCode & ec)900 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec)
901 {
902     RefPtr<Node> newNode = prpNewNode;
903 
904     ec = 0;
905 
906     if (!m_start.container()) {
907         ec = INVALID_STATE_ERR;
908         return;
909     }
910 
911     if (!newNode) {
912         ec = NOT_FOUND_ERR;
913         return;
914     }
915 
916     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
917     // the Range is read-only.
918     if (containedByReadOnly()) {
919         ec = NO_MODIFICATION_ALLOWED_ERR;
920         return;
921     }
922 
923     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
924     // not created from the same document.
925     if (newNode->document() != m_start.container()->document()) {
926         ec = WRONG_DOCUMENT_ERR;
927         return;
928     }
929 
930     // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
931     // does not allow children of the type of newNode or if newNode is an ancestor of the container.
932 
933     // an extra one here - if a text node is going to split, it must have a parent to insert into
934     bool startIsText = m_start.container()->isTextNode();
935     if (startIsText && !m_start.container()->parentNode()) {
936         ec = HIERARCHY_REQUEST_ERR;
937         return;
938     }
939 
940     // In the case where the container is a text node, we check against the container's parent, because
941     // text nodes get split up upon insertion.
942     Node* checkAgainst;
943     if (startIsText)
944         checkAgainst = m_start.container()->parentNode();
945     else
946         checkAgainst = m_start.container();
947 
948     Node::NodeType newNodeType = newNode->nodeType();
949     int numNewChildren;
950     if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) {
951         // check each child node, not the DocumentFragment itself
952         numNewChildren = 0;
953         for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) {
954             if (!checkAgainst->childTypeAllowed(c->nodeType())) {
955                 ec = HIERARCHY_REQUEST_ERR;
956                 return;
957             }
958             ++numNewChildren;
959         }
960     } else {
961         numNewChildren = 1;
962         if (!checkAgainst->childTypeAllowed(newNodeType)) {
963             ec = HIERARCHY_REQUEST_ERR;
964             return;
965         }
966     }
967 
968     for (Node* n = m_start.container(); n; n = n->parentNode()) {
969         if (n == newNode) {
970             ec = HIERARCHY_REQUEST_ERR;
971             return;
972         }
973     }
974 
975     // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
976     if (newNodeType == Node::ATTRIBUTE_NODE || newNodeType == Node::ENTITY_NODE
977             || newNodeType == Node::NOTATION_NODE || newNodeType == Node::DOCUMENT_NODE) {
978         ec = RangeException::INVALID_NODE_TYPE_ERR;
979         return;
980     }
981 
982     bool collapsed = m_start == m_end;
983     if (startIsText) {
984         RefPtr<Text> newText = static_cast<Text*>(m_start.container())->splitText(m_start.offset(), ec);
985         if (ec)
986             return;
987         m_start.container()->parentNode()->insertBefore(newNode.release(), newText.get(), ec);
988         if (ec)
989             return;
990 
991         // This special case doesn't seem to match the DOM specification, but it's currently required
992         // to pass Acid3. We might later decide to remove this.
993         if (collapsed)
994             m_end.setToBeforeChild(newText.get());
995     } else {
996         RefPtr<Node> lastChild;
997         if (collapsed)
998             lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
999 
1000         int startOffset = m_start.offset();
1001         m_start.container()->insertBefore(newNode.release(), m_start.container()->childNode(startOffset), ec);
1002         if (ec)
1003             return;
1004 
1005         // This special case doesn't seem to match the DOM specification, but it's currently required
1006         // to pass Acid3. We might later decide to remove this.
1007         if (collapsed)
1008             m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get());
1009     }
1010 }
1011 
toString(ExceptionCode & ec) const1012 String Range::toString(ExceptionCode& ec) const
1013 {
1014     if (!m_start.container()) {
1015         ec = INVALID_STATE_ERR;
1016         return String();
1017     }
1018 
1019     Vector<UChar> result;
1020 
1021     Node* pastLast = pastLastNode();
1022     for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) {
1023         if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
1024             String data = static_cast<CharacterData*>(n)->data();
1025             int length = data.length();
1026             int start = (n == m_start.container()) ? min(max(0, m_start.offset()), length) : 0;
1027             int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
1028             result.append(data.characters() + start, end - start);
1029         }
1030     }
1031 
1032     return String::adopt(result);
1033 }
1034 
toHTML() const1035 String Range::toHTML() const
1036 {
1037     return createMarkup(this);
1038 }
1039 
text() const1040 String Range::text() const
1041 {
1042     if (!m_start.container())
1043         return String();
1044 
1045     // We need to update layout, since plainText uses line boxes in the render tree.
1046     // FIXME: As with innerText, we'd like this to work even if there are no render objects.
1047     m_start.container()->document()->updateLayout();
1048 
1049     return plainText(this);
1050 }
1051 
createContextualFragment(const String & markup,ExceptionCode & ec) const1052 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionCode& ec) const
1053 {
1054     if (!m_start.container()) {
1055         ec = INVALID_STATE_ERR;
1056         return 0;
1057     }
1058 
1059     Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
1060     if (!element || !element->isHTMLElement()) {
1061         ec = NOT_SUPPORTED_ERR;
1062         return 0;
1063     }
1064 
1065     RefPtr<DocumentFragment> fragment = static_cast<HTMLElement*>(element)->createContextualFragment(markup);
1066     if (!fragment) {
1067         ec = NOT_SUPPORTED_ERR;
1068         return 0;
1069     }
1070 
1071     return fragment.release();
1072 }
1073 
1074 
detach(ExceptionCode & ec)1075 void Range::detach(ExceptionCode& ec)
1076 {
1077     // Check first to see if we've already detached:
1078     if (!m_start.container()) {
1079         ec = INVALID_STATE_ERR;
1080         return;
1081     }
1082 
1083     m_ownerDocument->detachRange(this);
1084 
1085     m_start.clear();
1086     m_end.clear();
1087 }
1088 
checkNodeWOffset(Node * n,int offset,ExceptionCode & ec) const1089 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionCode& ec) const
1090 {
1091     switch (n->nodeType()) {
1092         case Node::DOCUMENT_TYPE_NODE:
1093         case Node::ENTITY_NODE:
1094         case Node::NOTATION_NODE:
1095             ec = RangeException::INVALID_NODE_TYPE_ERR;
1096             return 0;
1097         case Node::CDATA_SECTION_NODE:
1098         case Node::COMMENT_NODE:
1099         case Node::TEXT_NODE:
1100             if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length())
1101                 ec = INDEX_SIZE_ERR;
1102             return 0;
1103         case Node::PROCESSING_INSTRUCTION_NODE:
1104             if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length())
1105                 ec = INDEX_SIZE_ERR;
1106             return 0;
1107         case Node::ATTRIBUTE_NODE:
1108         case Node::DOCUMENT_FRAGMENT_NODE:
1109         case Node::DOCUMENT_NODE:
1110         case Node::ELEMENT_NODE:
1111         case Node::ENTITY_REFERENCE_NODE:
1112         case Node::XPATH_NAMESPACE_NODE: {
1113             if (!offset)
1114                 return 0;
1115             Node* childBefore = n->childNode(offset - 1);
1116             if (!childBefore)
1117                 ec = INDEX_SIZE_ERR;
1118             return childBefore;
1119         }
1120     }
1121     ASSERT_NOT_REACHED();
1122     return 0;
1123 }
1124 
checkNodeBA(Node * n,ExceptionCode & ec) const1125 void Range::checkNodeBA(Node* n, ExceptionCode& ec) const
1126 {
1127     // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
1128     // Attr, Document or DocumentFragment node or part of a shadow DOM tree
1129     // or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation node.
1130 
1131     switch (n->nodeType()) {
1132         case Node::ATTRIBUTE_NODE:
1133         case Node::DOCUMENT_FRAGMENT_NODE:
1134         case Node::DOCUMENT_NODE:
1135         case Node::ENTITY_NODE:
1136         case Node::NOTATION_NODE:
1137             ec = RangeException::INVALID_NODE_TYPE_ERR;
1138             return;
1139         case Node::CDATA_SECTION_NODE:
1140         case Node::COMMENT_NODE:
1141         case Node::DOCUMENT_TYPE_NODE:
1142         case Node::ELEMENT_NODE:
1143         case Node::ENTITY_REFERENCE_NODE:
1144         case Node::PROCESSING_INSTRUCTION_NODE:
1145         case Node::TEXT_NODE:
1146         case Node::XPATH_NAMESPACE_NODE:
1147             break;
1148     }
1149 
1150     Node* root = n;
1151     while (Node* parent = root->parentNode())
1152         root = parent;
1153 
1154     switch (root->nodeType()) {
1155         case Node::ATTRIBUTE_NODE:
1156         case Node::DOCUMENT_NODE:
1157         case Node::DOCUMENT_FRAGMENT_NODE:
1158             break;
1159         case Node::CDATA_SECTION_NODE:
1160         case Node::COMMENT_NODE:
1161         case Node::DOCUMENT_TYPE_NODE:
1162         case Node::ELEMENT_NODE:
1163         case Node::ENTITY_NODE:
1164         case Node::ENTITY_REFERENCE_NODE:
1165         case Node::NOTATION_NODE:
1166         case Node::PROCESSING_INSTRUCTION_NODE:
1167         case Node::TEXT_NODE:
1168         case Node::XPATH_NAMESPACE_NODE:
1169             if (root->isShadowNode())
1170                 break;
1171             ec = RangeException::INVALID_NODE_TYPE_ERR;
1172             return;
1173     }
1174 }
1175 
cloneRange(ExceptionCode & ec) const1176 PassRefPtr<Range> Range::cloneRange(ExceptionCode& ec) const
1177 {
1178     if (!m_start.container()) {
1179         ec = INVALID_STATE_ERR;
1180         return 0;
1181     }
1182 
1183     return Range::create(m_ownerDocument, m_start.container(), m_start.offset(), m_end.container(), m_end.offset());
1184 }
1185 
setStartAfter(Node * refNode,ExceptionCode & ec)1186 void Range::setStartAfter(Node* refNode, ExceptionCode& ec)
1187 {
1188     if (!m_start.container()) {
1189         ec = INVALID_STATE_ERR;
1190         return;
1191     }
1192 
1193     if (!refNode) {
1194         ec = NOT_FOUND_ERR;
1195         return;
1196     }
1197 
1198     if (refNode->document() != m_ownerDocument) {
1199         ec = WRONG_DOCUMENT_ERR;
1200         return;
1201     }
1202 
1203     ec = 0;
1204     checkNodeBA(refNode, ec);
1205     if (ec)
1206         return;
1207 
1208     setStart(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
1209 }
1210 
setEndBefore(Node * refNode,ExceptionCode & ec)1211 void Range::setEndBefore(Node* refNode, ExceptionCode& ec)
1212 {
1213     if (!m_start.container()) {
1214         ec = INVALID_STATE_ERR;
1215         return;
1216     }
1217 
1218     if (!refNode) {
1219         ec = NOT_FOUND_ERR;
1220         return;
1221     }
1222 
1223     if (refNode->document() != m_ownerDocument) {
1224         ec = WRONG_DOCUMENT_ERR;
1225         return;
1226     }
1227 
1228     ec = 0;
1229     checkNodeBA(refNode, ec);
1230     if (ec)
1231         return;
1232 
1233     setEnd(refNode->parentNode(), refNode->nodeIndex(), ec);
1234 }
1235 
setEndAfter(Node * refNode,ExceptionCode & ec)1236 void Range::setEndAfter(Node* refNode, ExceptionCode& ec)
1237 {
1238     if (!m_start.container()) {
1239         ec = INVALID_STATE_ERR;
1240         return;
1241     }
1242 
1243     if (!refNode) {
1244         ec = NOT_FOUND_ERR;
1245         return;
1246     }
1247 
1248     if (refNode->document() != m_ownerDocument) {
1249         ec = WRONG_DOCUMENT_ERR;
1250         return;
1251     }
1252 
1253     ec = 0;
1254     checkNodeBA(refNode, ec);
1255     if (ec)
1256         return;
1257 
1258     setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
1259 
1260 }
1261 
selectNode(Node * refNode,ExceptionCode & ec)1262 void Range::selectNode(Node* refNode, ExceptionCode& ec)
1263 {
1264     if (!m_start.container()) {
1265         ec = INVALID_STATE_ERR;
1266         return;
1267     }
1268 
1269     if (!refNode) {
1270         ec = NOT_FOUND_ERR;
1271         return;
1272     }
1273 
1274     // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
1275     // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
1276     // node.
1277     for (Node* anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
1278         switch (anc->nodeType()) {
1279             case Node::ATTRIBUTE_NODE:
1280             case Node::CDATA_SECTION_NODE:
1281             case Node::COMMENT_NODE:
1282             case Node::DOCUMENT_FRAGMENT_NODE:
1283             case Node::DOCUMENT_NODE:
1284             case Node::ELEMENT_NODE:
1285             case Node::ENTITY_REFERENCE_NODE:
1286             case Node::PROCESSING_INSTRUCTION_NODE:
1287             case Node::TEXT_NODE:
1288             case Node::XPATH_NAMESPACE_NODE:
1289                 break;
1290             case Node::DOCUMENT_TYPE_NODE:
1291             case Node::ENTITY_NODE:
1292             case Node::NOTATION_NODE:
1293                 ec = RangeException::INVALID_NODE_TYPE_ERR;
1294                 return;
1295         }
1296     }
1297 
1298     switch (refNode->nodeType()) {
1299         case Node::CDATA_SECTION_NODE:
1300         case Node::COMMENT_NODE:
1301         case Node::DOCUMENT_TYPE_NODE:
1302         case Node::ELEMENT_NODE:
1303         case Node::ENTITY_REFERENCE_NODE:
1304         case Node::PROCESSING_INSTRUCTION_NODE:
1305         case Node::TEXT_NODE:
1306         case Node::XPATH_NAMESPACE_NODE:
1307             break;
1308         case Node::ATTRIBUTE_NODE:
1309         case Node::DOCUMENT_FRAGMENT_NODE:
1310         case Node::DOCUMENT_NODE:
1311         case Node::ENTITY_NODE:
1312         case Node::NOTATION_NODE:
1313             ec = RangeException::INVALID_NODE_TYPE_ERR;
1314             return;
1315     }
1316 
1317     ec = 0;
1318     setStartBefore(refNode, ec);
1319     if (ec)
1320         return;
1321     setEndAfter(refNode, ec);
1322 }
1323 
selectNodeContents(Node * refNode,ExceptionCode & ec)1324 void Range::selectNodeContents(Node* refNode, ExceptionCode& ec)
1325 {
1326     if (!m_start.container()) {
1327         ec = INVALID_STATE_ERR;
1328         return;
1329     }
1330 
1331     if (!refNode) {
1332         ec = NOT_FOUND_ERR;
1333         return;
1334     }
1335 
1336     // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
1337     // or DocumentType node.
1338     for (Node* n = refNode; n; n = n->parentNode()) {
1339         switch (n->nodeType()) {
1340             case Node::ATTRIBUTE_NODE:
1341             case Node::CDATA_SECTION_NODE:
1342             case Node::COMMENT_NODE:
1343             case Node::DOCUMENT_FRAGMENT_NODE:
1344             case Node::DOCUMENT_NODE:
1345             case Node::ELEMENT_NODE:
1346             case Node::ENTITY_REFERENCE_NODE:
1347             case Node::PROCESSING_INSTRUCTION_NODE:
1348             case Node::TEXT_NODE:
1349             case Node::XPATH_NAMESPACE_NODE:
1350                 break;
1351             case Node::DOCUMENT_TYPE_NODE:
1352             case Node::ENTITY_NODE:
1353             case Node::NOTATION_NODE:
1354                 ec = RangeException::INVALID_NODE_TYPE_ERR;
1355                 return;
1356         }
1357     }
1358 
1359     m_start.setToStartOfNode(refNode);
1360     m_end.setToEndOfNode(refNode);
1361 }
1362 
surroundContents(PassRefPtr<Node> passNewParent,ExceptionCode & ec)1363 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec)
1364 {
1365     RefPtr<Node> newParent = passNewParent;
1366 
1367     if (!m_start.container()) {
1368         ec = INVALID_STATE_ERR;
1369         return;
1370     }
1371 
1372     if (!newParent) {
1373         ec = NOT_FOUND_ERR;
1374         return;
1375     }
1376 
1377     // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
1378     // Document, or DocumentFragment node.
1379     switch (newParent->nodeType()) {
1380         case Node::ATTRIBUTE_NODE:
1381         case Node::DOCUMENT_FRAGMENT_NODE:
1382         case Node::DOCUMENT_NODE:
1383         case Node::DOCUMENT_TYPE_NODE:
1384         case Node::ENTITY_NODE:
1385         case Node::NOTATION_NODE:
1386             ec = RangeException::INVALID_NODE_TYPE_ERR;
1387             return;
1388         case Node::CDATA_SECTION_NODE:
1389         case Node::COMMENT_NODE:
1390         case Node::ELEMENT_NODE:
1391         case Node::ENTITY_REFERENCE_NODE:
1392         case Node::PROCESSING_INSTRUCTION_NODE:
1393         case Node::TEXT_NODE:
1394         case Node::XPATH_NAMESPACE_NODE:
1395             break;
1396     }
1397 
1398     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
1399     // the Range is read-only.
1400     if (containedByReadOnly()) {
1401         ec = NO_MODIFICATION_ALLOWED_ERR;
1402         return;
1403     }
1404 
1405     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
1406     // not created from the same document.
1407     if (newParent->document() != m_start.container()->document()) {
1408         ec = WRONG_DOCUMENT_ERR;
1409         return;
1410     }
1411 
1412     // Raise a HIERARCHY_REQUEST_ERR if m_start.container() doesn't accept children like newParent.
1413     Node* parentOfNewParent = m_start.container();
1414 
1415     // If m_start.container() is a character data node, it will be split and it will be its parent that will
1416     // need to accept newParent (or in the case of a comment, it logically "would" be inserted into the parent,
1417     // although this will fail below for another reason).
1418     if (parentOfNewParent->isCharacterDataNode())
1419         parentOfNewParent = parentOfNewParent->parentNode();
1420     if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->nodeType())) {
1421         ec = HIERARCHY_REQUEST_ERR;
1422         return;
1423     }
1424 
1425     if (m_start.container() == newParent || m_start.container()->isDescendantOf(newParent.get())) {
1426         ec = HIERARCHY_REQUEST_ERR;
1427         return;
1428     }
1429 
1430     // FIXME: Do we need a check if the node would end up with a child node of a type not
1431     // allowed by the type of node?
1432 
1433     // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text node.
1434     Node* startNonTextContainer = m_start.container();
1435     if (startNonTextContainer->nodeType() == Node::TEXT_NODE)
1436         startNonTextContainer = startNonTextContainer->parentNode();
1437     Node* endNonTextContainer = m_end.container();
1438     if (endNonTextContainer->nodeType() == Node::TEXT_NODE)
1439         endNonTextContainer = endNonTextContainer->parentNode();
1440     if (startNonTextContainer != endNonTextContainer) {
1441         ec = RangeException::BAD_BOUNDARYPOINTS_ERR;
1442         return;
1443     }
1444 
1445     ec = 0;
1446     while (Node* n = newParent->firstChild()) {
1447         newParent->removeChild(n, ec);
1448         if (ec)
1449             return;
1450     }
1451     RefPtr<DocumentFragment> fragment = extractContents(ec);
1452     if (ec)
1453         return;
1454     insertNode(newParent, ec);
1455     if (ec)
1456         return;
1457     newParent->appendChild(fragment.release(), ec);
1458     if (ec)
1459         return;
1460     selectNode(newParent.get(), ec);
1461 }
1462 
setStartBefore(Node * refNode,ExceptionCode & ec)1463 void Range::setStartBefore(Node* refNode, ExceptionCode& ec)
1464 {
1465     if (!m_start.container()) {
1466         ec = INVALID_STATE_ERR;
1467         return;
1468     }
1469 
1470     if (!refNode) {
1471         ec = NOT_FOUND_ERR;
1472         return;
1473     }
1474 
1475     if (refNode->document() != m_ownerDocument) {
1476         ec = WRONG_DOCUMENT_ERR;
1477         return;
1478     }
1479 
1480     ec = 0;
1481     checkNodeBA(refNode, ec);
1482     if (ec)
1483         return;
1484 
1485     setStart(refNode->parentNode(), refNode->nodeIndex(), ec);
1486 }
1487 
checkDeleteExtract(ExceptionCode & ec)1488 void Range::checkDeleteExtract(ExceptionCode& ec)
1489 {
1490     if (!m_start.container()) {
1491         ec = INVALID_STATE_ERR;
1492         return;
1493     }
1494 
1495     ec = 0;
1496     if (!commonAncestorContainer(ec) || ec)
1497         return;
1498 
1499     Node* pastLast = pastLastNode();
1500     for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) {
1501         if (n->isReadOnlyNode()) {
1502             ec = NO_MODIFICATION_ALLOWED_ERR;
1503             return;
1504         }
1505         if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1506             ec = HIERARCHY_REQUEST_ERR;
1507             return;
1508         }
1509     }
1510 
1511     if (containedByReadOnly()) {
1512         ec = NO_MODIFICATION_ALLOWED_ERR;
1513         return;
1514     }
1515 }
1516 
containedByReadOnly() const1517 bool Range::containedByReadOnly() const
1518 {
1519     for (Node* n = m_start.container(); n; n = n->parentNode()) {
1520         if (n->isReadOnlyNode())
1521             return true;
1522     }
1523     for (Node* n = m_end.container(); n; n = n->parentNode()) {
1524         if (n->isReadOnlyNode())
1525             return true;
1526     }
1527     return false;
1528 }
1529 
firstNode() const1530 Node* Range::firstNode() const
1531 {
1532     if (!m_start.container())
1533         return 0;
1534     if (m_start.container()->offsetInCharacters())
1535         return m_start.container();
1536     if (Node* child = m_start.container()->childNode(m_start.offset()))
1537         return child;
1538     if (!m_start.offset())
1539         return m_start.container();
1540     return m_start.container()->traverseNextSibling();
1541 }
1542 
editingStartPosition() const1543 Position Range::editingStartPosition() const
1544 {
1545     // This function is used by range style computations to avoid bugs like:
1546     // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
1547     // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up
1548     // with a spurious "mixed" style.
1549 
1550     VisiblePosition visiblePosition(m_start.container(), m_start.offset(), VP_DEFAULT_AFFINITY);
1551     if (visiblePosition.isNull())
1552         return Position();
1553 
1554     ExceptionCode ec = 0;
1555     // if the selection is a caret, just return the position, since the style
1556     // behind us is relevant
1557     if (collapsed(ec))
1558         return visiblePosition.deepEquivalent();
1559 
1560     // if the selection starts just before a paragraph break, skip over it
1561     if (isEndOfParagraph(visiblePosition))
1562         return visiblePosition.next().deepEquivalent().downstream();
1563 
1564     // otherwise, make sure to be at the start of the first selected node,
1565     // instead of possibly at the end of the last node before the selection
1566     return visiblePosition.deepEquivalent().downstream();
1567 }
1568 
shadowTreeRootNode() const1569 Node* Range::shadowTreeRootNode() const
1570 {
1571     return startContainer() ? startContainer()->shadowTreeRootNode() : 0;
1572 }
1573 
pastLastNode() const1574 Node* Range::pastLastNode() const
1575 {
1576     if (!m_start.container() || !m_end.container())
1577         return 0;
1578     if (m_end.container()->offsetInCharacters())
1579         return m_end.container()->traverseNextSibling();
1580     if (Node* child = m_end.container()->childNode(m_end.offset()))
1581         return child;
1582     return m_end.container()->traverseNextSibling();
1583 }
1584 
boundingBox()1585 IntRect Range::boundingBox()
1586 {
1587     IntRect result;
1588     Vector<IntRect> rects;
1589     textRects(rects);
1590     const size_t n = rects.size();
1591     for (size_t i = 0; i < n; ++i)
1592         result.unite(rects[i]);
1593     return result;
1594 }
1595 
textRects(Vector<IntRect> & rects,bool useSelectionHeight)1596 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight)
1597 {
1598     Node* startContainer = m_start.container();
1599     Node* endContainer = m_end.container();
1600 
1601     if (!startContainer || !endContainer)
1602         return;
1603 
1604     Node* stopNode = pastLastNode();
1605     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
1606         RenderObject* r = node->renderer();
1607         if (!r || !r->isText())
1608             continue;
1609         RenderText* renderText = toRenderText(r);
1610         int startOffset = node == startContainer ? m_start.offset() : 0;
1611         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
1612         renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight);
1613     }
1614 }
1615 
textQuads(Vector<FloatQuad> & quads,bool useSelectionHeight)1616 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight)
1617 {
1618     Node* startContainer = m_start.container();
1619     Node* endContainer = m_end.container();
1620 
1621     if (!startContainer || !endContainer)
1622         return;
1623 
1624     Node* stopNode = pastLastNode();
1625     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
1626         RenderObject* r = node->renderer();
1627         if (!r || !r->isText())
1628             continue;
1629         RenderText* renderText = toRenderText(r);
1630         int startOffset = node == startContainer ? m_start.offset() : 0;
1631         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
1632         renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight);
1633     }
1634 }
1635 
1636 #ifndef NDEBUG
1637 #define FormatBufferSize 1024
formatForDebugger(char * buffer,unsigned length) const1638 void Range::formatForDebugger(char* buffer, unsigned length) const
1639 {
1640     String result;
1641     String s;
1642 
1643     if (!m_start.container() || !m_end.container())
1644         result = "<empty>";
1645     else {
1646         char s[FormatBufferSize];
1647         result += "from offset ";
1648         result += String::number(m_start.offset());
1649         result += " of ";
1650         m_start.container()->formatForDebugger(s, FormatBufferSize);
1651         result += s;
1652         result += " to offset ";
1653         result += String::number(m_end.offset());
1654         result += " of ";
1655         m_end.container()->formatForDebugger(s, FormatBufferSize);
1656         result += s;
1657     }
1658 
1659     strncpy(buffer, result.utf8().data(), length - 1);
1660 }
1661 #undef FormatBufferSize
1662 #endif
1663 
operator ==(const Range & a,const Range & b)1664 bool operator==(const Range& a, const Range& b)
1665 {
1666     if (&a == &b)
1667         return true;
1668     // Not strictly legal C++, but in practice this can happen, and this check works
1669     // fine with GCC to detect such cases and return false rather than crashing.
1670     if (!&a || !&b)
1671         return false;
1672     return a.startPosition() == b.startPosition() && a.endPosition() == b.endPosition();
1673 }
1674 
rangeOfContents(Node * node)1675 PassRefPtr<Range> rangeOfContents(Node* node)
1676 {
1677     ASSERT(node);
1678     RefPtr<Range> range = Range::create(node->document());
1679     int exception = 0;
1680     range->selectNodeContents(node, exception);
1681     return range.release();
1682 }
1683 
maxStartOffset() const1684 int Range::maxStartOffset() const
1685 {
1686     if (!m_start.container())
1687         return 0;
1688     if (!m_start.container()->offsetInCharacters())
1689         return m_start.container()->childNodeCount();
1690     return m_start.container()->maxCharacterOffset();
1691 }
1692 
maxEndOffset() const1693 int Range::maxEndOffset() const
1694 {
1695     if (!m_end.container())
1696         return 0;
1697     if (!m_end.container()->offsetInCharacters())
1698         return m_end.container()->childNodeCount();
1699     return m_end.container()->maxCharacterOffset();
1700 }
1701 
boundaryNodeChildrenChanged(RangeBoundaryPoint & boundary,ContainerNode * container)1702 static inline void boundaryNodeChildrenChanged(RangeBoundaryPoint& boundary, ContainerNode* container)
1703 {
1704     if (!boundary.childBefore())
1705         return;
1706     if (boundary.container() != container)
1707         return;
1708     boundary.invalidateOffset();
1709 }
1710 
nodeChildrenChanged(ContainerNode * container)1711 void Range::nodeChildrenChanged(ContainerNode* container)
1712 {
1713     ASSERT(container);
1714     ASSERT(container->document() == m_ownerDocument);
1715     boundaryNodeChildrenChanged(m_start, container);
1716     boundaryNodeChildrenChanged(m_end, container);
1717 }
1718 
boundaryNodeWillBeRemoved(RangeBoundaryPoint & boundary,Node * nodeToBeRemoved)1719 static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved)
1720 {
1721     if (boundary.childBefore() == nodeToBeRemoved) {
1722         boundary.childBeforeWillBeRemoved();
1723         return;
1724     }
1725 
1726     for (Node* n = boundary.container(); n; n = n->parentNode()) {
1727         if (n == nodeToBeRemoved) {
1728             boundary.setToBeforeChild(nodeToBeRemoved);
1729             return;
1730         }
1731     }
1732 }
1733 
nodeWillBeRemoved(Node * node)1734 void Range::nodeWillBeRemoved(Node* node)
1735 {
1736     ASSERT(node);
1737     ASSERT(node->document() == m_ownerDocument);
1738     ASSERT(node != m_ownerDocument);
1739     ASSERT(node->parentNode());
1740     boundaryNodeWillBeRemoved(m_start, node);
1741     boundaryNodeWillBeRemoved(m_end, node);
1742 }
1743 
boundaryTextInserted(RangeBoundaryPoint & boundary,Node * text,unsigned offset,unsigned length)1744 static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
1745 {
1746     if (boundary.container() != text)
1747         return;
1748     unsigned boundaryOffset = boundary.offset();
1749     if (offset >= boundaryOffset)
1750         return;
1751     boundary.setOffset(boundaryOffset + length);
1752 }
1753 
textInserted(Node * text,unsigned offset,unsigned length)1754 void Range::textInserted(Node* text, unsigned offset, unsigned length)
1755 {
1756     ASSERT(text);
1757     ASSERT(text->document() == m_ownerDocument);
1758     boundaryTextInserted(m_start, text, offset, length);
1759     boundaryTextInserted(m_end, text, offset, length);
1760 }
1761 
boundaryTextRemoved(RangeBoundaryPoint & boundary,Node * text,unsigned offset,unsigned length)1762 static inline void boundaryTextRemoved(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
1763 {
1764     if (boundary.container() != text)
1765         return;
1766     unsigned boundaryOffset = boundary.offset();
1767     if (offset >= boundaryOffset)
1768         return;
1769     if (offset + length >= boundaryOffset)
1770         boundary.setOffset(offset);
1771     else
1772         boundary.setOffset(boundaryOffset - length);
1773 }
1774 
textRemoved(Node * text,unsigned offset,unsigned length)1775 void Range::textRemoved(Node* text, unsigned offset, unsigned length)
1776 {
1777     ASSERT(text);
1778     ASSERT(text->document() == m_ownerDocument);
1779     boundaryTextRemoved(m_start, text, offset, length);
1780     boundaryTextRemoved(m_end, text, offset, length);
1781 }
1782 
boundaryTextNodesMerged(RangeBoundaryPoint & boundary,NodeWithIndex & oldNode,unsigned offset)1783 static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset)
1784 {
1785     if (boundary.container() == oldNode.node())
1786         boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);
1787     else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())
1788         boundary.set(oldNode.node()->previousSibling(), offset, 0);
1789 }
1790 
textNodesMerged(NodeWithIndex & oldNode,unsigned offset)1791 void Range::textNodesMerged(NodeWithIndex& oldNode, unsigned offset)
1792 {
1793     ASSERT(oldNode.node());
1794     ASSERT(oldNode.node()->document() == m_ownerDocument);
1795     ASSERT(oldNode.node()->parentNode());
1796     ASSERT(oldNode.node()->isTextNode());
1797     ASSERT(oldNode.node()->previousSibling());
1798     ASSERT(oldNode.node()->previousSibling()->isTextNode());
1799     boundaryTextNodesMerged(m_start, oldNode, offset);
1800     boundaryTextNodesMerged(m_end, oldNode, offset);
1801 }
1802 
boundaryTextNodesSplit(RangeBoundaryPoint & boundary,Text * oldNode)1803 static inline void boundaryTextNodesSplit(RangeBoundaryPoint& boundary, Text* oldNode)
1804 {
1805     if (boundary.container() != oldNode)
1806         return;
1807     unsigned boundaryOffset = boundary.offset();
1808     if (boundaryOffset <= oldNode->length())
1809         return;
1810     boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);
1811 }
1812 
textNodeSplit(Text * oldNode)1813 void Range::textNodeSplit(Text* oldNode)
1814 {
1815     ASSERT(oldNode);
1816     ASSERT(oldNode->document() == m_ownerDocument);
1817     ASSERT(oldNode->parentNode());
1818     ASSERT(oldNode->isTextNode());
1819     ASSERT(oldNode->nextSibling());
1820     ASSERT(oldNode->nextSibling()->isTextNode());
1821     boundaryTextNodesSplit(m_start, oldNode);
1822     boundaryTextNodesSplit(m_end, oldNode);
1823 }
1824 
expand(const String & unit,ExceptionCode & ec)1825 void Range::expand(const String& unit, ExceptionCode& ec)
1826 {
1827     VisiblePosition start(startPosition());
1828     VisiblePosition end(endPosition());
1829     if (unit == "word") {
1830         start = startOfWord(start);
1831         end = endOfWord(end);
1832     } else if (unit == "sentence") {
1833         start = startOfSentence(start);
1834         end = endOfSentence(end);
1835     } else if (unit == "block") {
1836         start = startOfParagraph(start);
1837         end = endOfParagraph(end);
1838     } else if (unit == "document") {
1839         start = startOfDocument(start);
1840         end = endOfDocument(end);
1841     } else
1842         return;
1843     setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec);
1844     setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
1845 }
1846 
getClientRects() const1847 PassRefPtr<ClientRectList> Range::getClientRects() const
1848 {
1849     if (!m_start.container())
1850         return 0;
1851 
1852     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1853 
1854     Vector<FloatQuad> quads;
1855     getBorderAndTextQuads(quads);
1856 
1857     return ClientRectList::create(quads);
1858 }
1859 
getBoundingClientRect() const1860 PassRefPtr<ClientRect> Range::getBoundingClientRect() const
1861 {
1862     if (!m_start.container())
1863         return 0;
1864 
1865     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1866 
1867     Vector<FloatQuad> quads;
1868     getBorderAndTextQuads(quads);
1869 
1870     if (quads.isEmpty())
1871         return ClientRect::create();
1872 
1873     IntRect result;
1874     for (size_t i = 0; i < quads.size(); ++i)
1875         result.unite(quads[i].enclosingBoundingBox());
1876 
1877     return ClientRect::create(result);
1878 }
1879 
adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad> & quads,Document * document,RenderObject * renderer)1880 static void adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer)
1881 {
1882     FrameView* view = document->view();
1883     if (!view)
1884         return;
1885 
1886     IntRect visibleContentRect = view->visibleContentRect();
1887     for (size_t i = 0; i < quads.size(); ++i) {
1888         quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
1889         adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
1890     }
1891 }
1892 
getBorderAndTextQuads(Vector<FloatQuad> & quads) const1893 void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
1894 {
1895     Node* startContainer = m_start.container();
1896     Node* endContainer = m_end.container();
1897     Node* stopNode = pastLastNode();
1898 
1899     HashSet<Node*> nodeSet;
1900     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
1901         if (node->isElementNode())
1902             nodeSet.add(node);
1903     }
1904 
1905     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
1906         if (node->isElementNode()) {
1907             if (!nodeSet.contains(node->parentNode())) {
1908                 if (RenderBoxModelObject* renderBoxModelObject = static_cast<Element*>(node)->renderBoxModelObject()) {
1909                     Vector<FloatQuad> elementQuads;
1910                     renderBoxModelObject->absoluteQuads(elementQuads);
1911                     adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, m_ownerDocument.get(), renderBoxModelObject);
1912 
1913                     quads.append(elementQuads);
1914                 }
1915             }
1916         } else if (node->isTextNode()) {
1917             if (RenderObject* renderer = static_cast<Text*>(node)->renderer()) {
1918                 RenderText* renderText = toRenderText(renderer);
1919                 int startOffset = (node == startContainer) ? m_start.offset() : 0;
1920                 int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX;
1921 
1922                 Vector<FloatQuad> textQuads;
1923                 renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
1924                 adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, m_ownerDocument.get(), renderText);
1925 
1926                 quads.append(textQuads);
1927             }
1928         }
1929     }
1930 }
1931 
1932 } // namespace WebCore
1933 
1934 #ifndef NDEBUG
1935 
showTree(const WebCore::Range * range)1936 void showTree(const WebCore::Range* range)
1937 {
1938     if (range && range->boundaryPointsValid()) {
1939         WebCore::Position start = range->startPosition();
1940         WebCore::Position end = range->endPosition();
1941         start.node()->showTreeAndMark(start.node(), "S", end.node(), "E");
1942         fprintf(stderr, "start offset: %d, end offset: %d\n", start.deprecatedEditingOffset(), end.deprecatedEditingOffset());
1943     }
1944 }
1945 
1946 #endif
1947