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);
}
Example #2
0
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);
}