⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 visible_units.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "visible_units.h"#include "Document.h"#include "Element.h"#include "HTMLNames.h"#include "RenderBlock.h"#include "RenderLayer.h"#include "TextBoundaries.h"#include "TextBreakIterator.h"#include "TextIterator.h"#include "VisiblePosition.h"#include "htmlediting.h"namespace WebCore {using namespace HTMLNames;static VisiblePosition previousBoundary(const VisiblePosition &c, unsigned (*searchFunction)(const UChar *, unsigned)){    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);        int exception = 0;    searchRange->setStart(start.node(), start.offset(), exception);    searchRange->setEnd(end.node(), end.offset(), exception);        ASSERT(!exception);    if (exception)        return VisiblePosition();            SimplifiedBackwardsTextIterator it(searchRange.get());    Vector<UChar, 1024> string;    unsigned next = 0;    bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;    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());        if (next != 0)            break;        it.advance();    }        if (it.atEnd() && next == 0) {        pos = it.range()->startPosition();    } else if (next != 0) {        Node *node = it.range()->startContainer(exception);        if (node->isTextNode() || (node->renderer() && node->renderer()->isBR()))            // The next variable contains a usable index into a text node            pos = Position(node, next);        else {            // Use the end of the found range, the start is not guaranteed to            // be correct.            Position end = it.range()->endPosition();            VisiblePosition boundary(end);            unsigned i = it.length() - next;            while (i--)                boundary = boundary.previous();            return boundary;        }    }    return VisiblePosition(pos, DOWNSTREAM);}static VisiblePosition nextBoundary(const VisiblePosition &c, unsigned (*searchFunction)(const UChar *, unsigned)){    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();    RefPtr<Range> searchRange(d->createRange());    Position start(rangeCompliantEquivalent(pos));    ExceptionCode ec = 0;    searchRange->selectNodeContents(boundary, ec);    searchRange->setStart(start.node(), start.offset(), ec);    TextIterator it(searchRange.get(), true);    Vector<UChar, 1024> string;    unsigned next = 0;    bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;    while (!it.atEnd()) {        // Keep asking the iterator for chunks until the search function        // returns an end value not equal to the length of the string passed to it.        if (!inTextSecurityMode)            string.append(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.append(iteratorString.characters(), iteratorString.length());        }        next = searchFunction(string.data(), string.size());        if (next != string.size())            break;        it.advance();    }        if (it.atEnd() && next == string.size()) {        pos = it.range()->startPosition();    } else if (next != 0) {        // Use the character iterator to translate the next value into a DOM position.        CharacterIterator charIt(searchRange.get(), true);        charIt.advance(next - 1);        pos = charIt.range()->endPosition();                // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)        VisiblePosition visPos = VisiblePosition(pos);        if (visPos == VisiblePosition(charIt.range()->startPosition()))            pos = visPos.next(true).deepEquivalent();    }    // generate VisiblePosition, use UPSTREAM affinity if possible    return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);}// ---------static unsigned startWordBoundary(const UChar* characters, unsigned length){    int start, end;    findWordBoundary(characters, length, length, &start, &end);    return start;}VisiblePosition startOfWord(const VisiblePosition &c, EWordSide side){    // FIXME: This returns a null VP for c at the start of the document    // and side == LeftWordIfOnBoundary    VisiblePosition p = c;    if (side == RightWordIfOnBoundary) {        // at paragraph end, the startofWord is the current position        if (isEndOfParagraph(c))            return c;                p = c.next();        if (p.isNull())            return c;    }    return previousBoundary(p, startWordBoundary);}static unsigned endWordBoundary(const UChar* characters, unsigned length){    int start, end;    findWordBoundary(characters, length, 0, &start, &end);    return end;}VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side){    VisiblePosition p = c;    if (side == LeftWordIfOnBoundary) {        if (isStartOfParagraph(c))            return c;                    p = c.previous();        if (p.isNull())            return c;    } else if (isEndOfParagraph(c))        return c;        return nextBoundary(p, endWordBoundary);}static unsigned previousWordPositionBoundary(const UChar* characters, unsigned length){    return findNextWordFromIndex(characters, length, length, false);}VisiblePosition previousWordPosition(const VisiblePosition &c){    VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);    return c.honorEditableBoundaryAtOrAfter(prev);}static unsigned nextWordPositionBoundary(const UChar* characters, unsigned length){    return findNextWordFromIndex(characters, length, 0, true);}VisiblePosition nextWordPosition(const VisiblePosition &c){    VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);        return c.honorEditableBoundaryAtOrBefore(next);}// ---------static RootInlineBox *rootBoxForLine(const VisiblePosition &c){    Position p = c.deepEquivalent();    Node *node = p.node();    if (!node)        return 0;    RenderObject *renderer = node->renderer();    if (!renderer)        return 0;    InlineBox* box;    int offset;    c.getInlineBoxAndOffset(box, offset);        return box ? box->root() : 0;}static VisiblePosition positionAvoidingFirstPositionInTable(const VisiblePosition& c){    // return table offset 0 instead of the first VisiblePosition inside the table    VisiblePosition previous = c.previous();    if (isLastPositionBeforeTable(previous))        return previous;        return c;}static VisiblePosition startPositionForLine(const VisiblePosition& c){    if (c.isNull())        return VisiblePosition();    RootInlineBox *rootBox = rootBoxForLine(c);    if (!rootBox) {        // There are VisiblePositions at offset 0 in blocks without        // RootInlineBoxes, like empty editable blocks and bordered blocks.        Position p = c.deepEquivalent();        if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0)            return positionAvoidingFirstPositionInTable(c);                return VisiblePosition();    }        // Generated content (e.g. list markers and CSS :before and :after    // pseudoelements) have no corresponding DOM element, and so cannot be    // represented by a VisiblePosition.  Use whatever follows instead.    InlineBox *startBox = rootBox->firstLeafChild();    Node *startNode;    while (1) {        if (!startBox)            return VisiblePosition();        RenderObject *startRenderer = startBox->renderer();        if (!startRenderer)            return VisiblePosition();        startNode = startRenderer->node();        if (startNode)            break;                startBox = startBox->nextLeafChild();    }        int startOffset = 0;    if (startBox->isInlineTextBox()) {        InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);        startOffset = startTextBox->start();    }  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -