Example #1
0
void DOMSelection::addRange(Range* newRange)
{
    if (!m_frame)
        return;

    // FIXME: Should we throw DOMException for error cases below?
    if (!newRange) {
        addConsoleError("The given range is null.");
        return;
    }

    if (!newRange->startContainer()) {
        addConsoleError("The given range has no container. Perhaps 'detach()' has been invoked on it?");
        return;
    }

    FrameSelection& selection = m_frame->selection();

    if (selection.isNone()) {
        selection.setSelectedRange(newRange, VP_DEFAULT_AFFINITY);
        return;
    }

    RefPtrWillBeRawPtr<Range> originalRange = selection.firstRange();

    if (originalRange->startContainer()->document() != newRange->startContainer()->document()) {
        addConsoleError("The given range does not belong to the current selection's document.");
        return;
    }
    if (originalRange->startContainer()->treeScope() != newRange->startContainer()->treeScope()) {
        addConsoleError("The given range and the current selection belong to two different document fragments.");
        return;
    }

    if (originalRange->compareBoundaryPoints(Range::START_TO_END, newRange, ASSERT_NO_EXCEPTION) < 0
        || newRange->compareBoundaryPoints(Range::START_TO_END, originalRange.get(), ASSERT_NO_EXCEPTION) < 0) {
        addConsoleError("Discontiguous selection is not supported.");
        return;
    }

    // FIXME: "Merge the ranges if they intersect" is Blink-specific behavior; other browsers supporting discontiguous
    // selection (obviously) keep each Range added and return it in getRangeAt(). But it's unclear if we can really
    // do the same, since we don't support discontiguous selection. Further discussions at
    // <https://code.google.com/p/chromium/issues/detail?id=353069>.

    Range* start = originalRange->compareBoundaryPoints(Range::START_TO_START, newRange, ASSERT_NO_EXCEPTION) < 0 ? originalRange.get() : newRange;
    Range* end = originalRange->compareBoundaryPoints(Range::END_TO_END, newRange, ASSERT_NO_EXCEPTION) < 0 ? newRange : originalRange.get();
    RefPtrWillBeRawPtr<Range> merged = Range::create(originalRange->startContainer()->document(), start->startContainer(), start->startOffset(), end->endContainer(), end->endOffset());
    EAffinity affinity = selection.selection().affinity();
    selection.setSelectedRange(merged.get(), affinity);
}