PassRefPtr<Range> VisibleSelection::firstRange() const { if (isNone()) return 0; Position start = rangeCompliantEquivalent(m_start); Position end = rangeCompliantEquivalent(m_end); return Range::create(start.node()->document(), start, end); }
PassRefPtr<Range> Selection::toRange() const { if (isNone()) return 0; // Make sure we have an updated layout since this function is called // in the course of running edit commands which modify the DOM. // Failing to call this can result in equivalentXXXPosition calls returning // incorrect results. m_start.node()->document()->updateLayout(); Position s, e; if (isCaret()) { // If the selection is a caret, move the range start upstream. This helps us match // the conventions of text editors tested, which make style determinations based // on the character before the caret, if any. s = rangeCompliantEquivalent(m_start.upstream()); e = s; } else { // If the selection is a range, select the minimum range that encompasses the selection. // Again, this is to match the conventions of text editors tested, which make style // determinations based on the first character of the selection. // For instance, this operation helps to make sure that the "X" selected below is the // only thing selected. The range should not be allowed to "leak" out to the end of the // previous text node, or to the beginning of the next text node, each of which has a // different style. // // On a treasure map, <b>X</b> marks the spot. // ^ selected // ASSERT(isRange()); s = m_start.downstream(); e = m_end.upstream(); if (Range::compareBoundaryPoints(s.node(), s.offset(), e.node(), e.offset()) > 0) { // Make sure the start is before the end. // The end can wind up before the start if collapsed whitespace is the only thing selected. Position tmp = s; s = e; e = tmp; } s = rangeCompliantEquivalent(s); e = rangeCompliantEquivalent(e); } ExceptionCode ec = 0; RefPtr<Range> result(new Range(s.node()->document())); result->setStart(s.node(), s.offset(), ec); if (ec) { LOG_ERROR("Exception setting Range start from Selection: %d", ec); return 0; } result->setEnd(e.node(), e.offset(), ec); if (ec) { LOG_ERROR("Exception setting Range end from Selection: %d", ec); return 0; } return result.release(); }
PassRefPtr<Range> VisibleSelection::toNormalizedRange() const { if (isNone()) return 0; // Make sure we have an updated layout since this function is called // in the course of running edit commands which modify the DOM. // Failing to call this can result in equivalentXXXPosition calls returning // incorrect results. m_start.node()->document()->updateLayout(); // Check again, because updating layout can clear the selection. if (isNone()) return 0; Position s, e; if (isCaret()) { // If the selection is a caret, move the range start upstream. This helps us match // the conventions of text editors tested, which make style determinations based // on the character before the caret, if any. s = rangeCompliantEquivalent(m_start.upstream()); e = s; } else { // If the selection is a range, select the minimum range that encompasses the selection. // Again, this is to match the conventions of text editors tested, which make style // determinations based on the first character of the selection. // For instance, this operation helps to make sure that the "X" selected below is the // only thing selected. The range should not be allowed to "leak" out to the end of the // previous text node, or to the beginning of the next text node, each of which has a // different style. // // On a treasure map, <b>X</b> marks the spot. // ^ selected // ASSERT(isRange()); s = m_start.downstream(); e = m_end.upstream(); if (comparePositions(s, e) > 0) { // Make sure the start is before the end. // The end can wind up before the start if collapsed whitespace is the only thing selected. Position tmp = s; s = e; e = tmp; } s = rangeCompliantEquivalent(s); e = rangeCompliantEquivalent(e); } // VisibleSelections are supposed to always be valid. This constructor will ASSERT // if a valid range could not be created, which is fine for this callsite. return Range::create(s.node()->document(), s, e); }
static PassRefPtr<Range> makeSearchRange(const Position& pos) { Node* n = pos.node(); if (!n) return 0; Document* d = n->document(); Node* de = d->documentElement(); if (!de) return 0; Node* boundary = n->enclosingBlockFlowElement(); if (!boundary) return 0; RefPtr<Range> searchRange(Range::create(d)); ExceptionCode ec = 0; Position start(rangeCompliantEquivalent(pos)); searchRange->selectNodeContents(boundary, ec); searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec); ASSERT(!ec); if (ec) return 0; return searchRange.release(); }
static Position extentPosition(const VisibleSelection& selection) { return rangeCompliantEquivalent(selection.extent()); }
static Position basePosition(const VisibleSelection& selection) { return rangeCompliantEquivalent(selection.base()); }
static Position focusPosition(const VisibleSelection& selection) { Position focus = selection.isBaseFirst() ? selection.end() : selection.start(); return rangeCompliantEquivalent(focus); }
static Position anchorPosition(const VisibleSelection& selection) { Position anchor = selection.isBaseFirst() ? selection.start() : selection.end(); return rangeCompliantEquivalent(anchor); }