示例#1
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.anchorNode()->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 = m_start.upstream().parentAnchoredEquivalent();
        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 = s.parentAnchoredEquivalent();
        e = e.parentAnchoredEquivalent();
    }

    if (!s.containerNode() || !e.containerNode())
        return 0;

    // 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.anchorNode()->document(), s, e);
}