Пример #1
0
PassRefPtr<Range> trimWhitespaceFromRange(VisiblePosition startPosition, VisiblePosition endPosition)
{
    if (startPosition == endPosition || isRangeTextAllWhitespace(startPosition, endPosition))
        return 0;

    while (isWhitespace(startPosition.characterAfter()))
        startPosition = startPosition.next();

    while (isWhitespace(endPosition.characterBefore()))
        endPosition = endPosition.previous();

    return makeRange(startPosition, endPosition);
}
Пример #2
0
static VisibleSelection wordAtPositionForAtkBoundary(const AccessibilityObject* /*coreObject*/, const VisiblePosition& position, AtkTextBoundary boundaryType)
{
    VisiblePosition startPosition;
    VisiblePosition endPosition;

    switch (boundaryType) {
    case ATK_TEXT_BOUNDARY_WORD_START:
        // isStartOfWord() returns true both when at the beginning of a "real" word
        // as when at the beginning of a whitespace range between two "real" words,
        // since that whitespace is considered a "word" as well. And in case we are
        // already at the beginning of a "real" word we do not need to look backwards.
        if (isStartOfWord(position) && isWhitespace(position.characterBefore()))
            startPosition = position;
        else
            startPosition = previousWordPosition(position);
        endPosition = nextWordStartPosition(startPosition);

        // We need to make sure that we look for the word in the current line when
        // we are at the beginning of a new line, and not look into the previous one
        // at all, which might happen when lines belong to different nodes.
        if (isStartOfLine(position) && isStartOfLine(endPosition)) {
            startPosition = endPosition;
            endPosition = nextWordStartPosition(startPosition);
        }
        break;

    case ATK_TEXT_BOUNDARY_WORD_END:
        startPosition = previousWordEndPosition(position);
        endPosition = nextWordPosition(startPosition);
        break;

    default:
        ASSERT_NOT_REACHED();
    }

    VisibleSelection selectedWord(startPosition, endPosition);

    // We mark the selection as 'upstream' so we can use that information later,
    // when finding the actual offsets in getSelectionOffsetsForObject().
    if (boundaryType == ATK_TEXT_BOUNDARY_WORD_END)
        selectedWord.setAffinity(UPSTREAM);

    return selectedWord;
}
Пример #3
0
static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
{
    Position pos = c.deepEquivalent();
    Node *n = pos.node();
    if (!n)
        return VisiblePosition();
    Document *d = n->document();
    Node *de = d->documentElement();
    if (!de)
        return VisiblePosition();
    Node *boundary = n->enclosingBlockFlowElement();
    if (!boundary)
        return VisiblePosition();
    bool isContentEditable = boundary->isContentEditable();
    while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
        boundary = boundary->parentNode();

    Position start = rangeCompliantEquivalent(Position(boundary, 0));
    Position end = rangeCompliantEquivalent(pos);
    RefPtr<Range> searchRange = Range::create(d);
    
    Vector<UChar, 1024> string;
    unsigned suffixLength = 0;

    ExceptionCode ec = 0;
    if (requiresContextForWordBoundary(c.characterBefore())) {
        RefPtr<Range> forwardsScanRange(d->createRange());
        forwardsScanRange->setEndAfter(boundary, ec);
        forwardsScanRange->setStart(end.node(), end.deprecatedEditingOffset(), ec);
        TextIterator forwardsIterator(forwardsScanRange.get());
        while (!forwardsIterator.atEnd()) {
            const UChar* characters = forwardsIterator.characters();
            int length = forwardsIterator.length();
            int i = endOfFirstWordBoundaryContext(characters, length);
            string.append(characters, i);
            suffixLength += i;
            if (i < length)
                break;
            forwardsIterator.advance();
        }
    }

    searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec);
    searchRange->setEnd(end.node(), end.deprecatedEditingOffset(), ec);
    
    ASSERT(!ec);
    if (ec)
        return VisiblePosition();

    SimplifiedBackwardsTextIterator it(searchRange.get());
    unsigned next = 0;
    bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
    bool needMoreContext = false;
    while (!it.atEnd()) {
        // iterate to get chunks until the searchFunction returns a non-zero value.
        if (!inTextSecurityMode) 
            string.prepend(it.characters(), it.length());
        else {
            // Treat bullets used in the text security mode as regular characters when looking for boundaries
            String iteratorString(it.characters(), it.length());
            iteratorString = iteratorString.impl()->secure('x');
            string.prepend(iteratorString.characters(), iteratorString.length());
        }
        next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
        if (next != 0)
            break;
        it.advance();
    }
    if (needMoreContext) {
        // The last search returned the beginning of the buffer and asked for more context,
        // but there is no earlier text. Force a search with what's available.
        next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
        ASSERT(!needMoreContext);
    }

    if (it.atEnd() && next == 0) {
        pos = it.range()->startPosition();
    } else if (next != 0) {
        Node *node = it.range()->startContainer(ec);
        if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
            // The next variable contains a usable index into a text node
            pos = Position(node, next);
        else {
            // Use the character iterator to translate the next value into a DOM position.
            BackwardsCharacterIterator charIt(searchRange.get());
            charIt.advance(string.size() - suffixLength - next);
            pos = charIt.range()->endPosition();
        }
    }

    return VisiblePosition(pos, DOWNSTREAM);
}