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

📄 position.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2004, 2005, 2006, 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 "Position.h"#include "CSSComputedStyleDeclaration.h"#include "CString.h"#include "CharacterNames.h"#include "Logging.h"#include "PositionIterator.h"#include "RenderBlock.h"#include "Text.h"#include "TextIterator.h"#include "VisiblePosition.h"#include "htmlediting.h"#include "visible_units.h"#include <stdio.h>  namespace WebCore {using namespace HTMLNames;static Node* nextRenderedEditable(Node* node){    while (1) {        node = node->nextEditable();        if (!node)            return 0;        RenderObject* renderer = node->renderer();        if (!renderer)            continue;        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))            return node;    }    return 0;}static Node* previousRenderedEditable(Node* node){    while (1) {        node = node->previousEditable();        if (!node)            return 0;        RenderObject* renderer = node->renderer();        if (!renderer)            continue;        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))            return node;    }    return 0;}Element* Position::documentElement() const{    if (Node* n = node())        if (Element* e = n->document()->documentElement())            return e;    return 0;}Element *Position::element() const{    Node *n;    for (n = node(); n && !n->isElementNode(); n = n->parentNode())        ; // empty loop body    return static_cast<Element *>(n);}PassRefPtr<CSSComputedStyleDeclaration> Position::computedStyle() const{    Element* elem = element();    if (!elem)        return 0;    return WebCore::computedStyle(elem);}Position Position::previous(PositionMoveType moveType) const{    Node* n = node();    if (!n)        return *this;        int o = offset();    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.    ASSERT(o >= 0);    if (o > 0) {        Node* child = n->childNode(o - 1);        if (child)            return Position(child, maxDeepOffset(child));        // There are two reasons child might be 0:        //   1) The node is node like a text node that is not an element, and therefore has no children.        //      Going backward one character at a time is correct.        //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.        //      Going from 1 to 0 is correct.        switch (moveType) {        case CodePoint:            return Position(n, o - 1);        case Character:            return Position(n, uncheckedPreviousOffset(n, o));        case BackwardDeletion:            return Position(n, uncheckedPreviousOffsetForBackwardDeletion(n, o));        }    }    Node* parent = n->parentNode();    if (!parent)        return *this;    return Position(parent, n->nodeIndex());}Position Position::next(PositionMoveType moveType) const{    ASSERT(moveType != BackwardDeletion);    Node* n = node();    if (!n)        return *this;        int o = offset();    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.    ASSERT(o >= 0);    Node* child = n->childNode(o);    if (child || !n->hasChildNodes() && o < maxDeepOffset(n)) {        if (child)            return Position(child, 0);                    // There are two reasons child might be 0:        //   1) The node is node like a text node that is not an element, and therefore has no children.        //      Going forward one character at a time is correct.        //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.        //      Going from 0 to 1 is correct.        return Position(n, (moveType == Character) ? uncheckedNextOffset(n, o) : o + 1);    }    Node* parent = n->parentNode();    if (!parent)        return *this;    return Position(parent, n->nodeIndex() + 1);}int Position::uncheckedPreviousOffset(const Node* n, int current){    return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;}int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current){    return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;}int Position::uncheckedNextOffset(const Node* n, int current){    return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;}bool Position::atStart() const{    Node *n = node();    if (!n)        return true;        return offset() <= 0 && n->parent() == 0;}bool Position::atEnd() const{    Node *n = node();    if (!n)        return true;        return n->parent() == 0 && offset() >= maxDeepOffset(n);}int Position::renderedOffset() const{    if (!node()->isTextNode())        return offset();       if (!node()->renderer())        return offset();                        int result = 0;    RenderText *textRenderer = toRenderText(node()->renderer());    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {        int start = box->start();        int end = box->start() + box->len();        if (offset() < start)            return result;        if (offset() <= end) {            result += offset() - start;            return result;        }        result += box->len();    }    return result;}// return first preceding DOM position rendered at a different location, or "this"Position Position::previousCharacterPosition(EAffinity affinity) const{    if (isNull())        return Position();    Node *fromRootEditableElement = node()->rootEditableElement();    bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));    bool rendered = isCandidate();        Position currentPos = *this;    while (!currentPos.atStart()) {        currentPos = currentPos.previous();        if (currentPos.node()->rootEditableElement() != fromRootEditableElement)            return *this;        if (atStartOfLine || !rendered) {            if (currentPos.isCandidate())                return currentPos;        } else if (rendersInDifferentPosition(currentPos))            return currentPos;    }        return *this;}// return first following position rendered at a different location, or "this"Position Position::nextCharacterPosition(EAffinity affinity) const{    if (isNull())        return Position();    Node *fromRootEditableElement = node()->rootEditableElement();    bool atEndOfLine = isEndOfLine(VisiblePosition(*this, affinity));    bool rendered = isCandidate();        Position currentPos = *this;    while (!currentPos.atEnd()) {        currentPos = currentPos.next();        if (currentPos.node()->rootEditableElement() != fromRootEditableElement)            return *this;        if (atEndOfLine || !rendered) {            if (currentPos.isCandidate())                return currentPos;        } else if (rendersInDifferentPosition(currentPos))            return currentPos;    }        return *this;}// Whether or not [node, 0] and [node, maxDeepOffset(node)] are their own VisiblePositions.// If true, adjacent candidates are visually distinct.// FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.// FIXME: Share code with isCandidate, if possible.static bool endsOfNodeAreVisuallyDistinctPositions(Node* node){    if (!node || !node->renderer())        return false;            if (!node->renderer()->isInline())        return true;            // Don't include inline tables.    if (node->hasTagName(tableTag))        return false;        // There is a VisiblePosition inside an empty inline-block container.    return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();}static Node* enclosingVisualBoundary(Node* node){    while (node && !endsOfNodeAreVisuallyDistinctPositions(node))        node = node->parentNode();            return node;}// upstream() and downstream() want to return positions that are either in a// text node or at just before a non-text node.  This method checks for that.static bool isStreamer(const PositionIterator& pos){    if (!pos.node())        return true;            if (isAtomicNode(pos.node()))        return true;            return pos.atStartOfNode();}// This function and downstream() are used for moving back and forth between visually equivalent candidates.// For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates // that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate // and downstream() will return the right one.// Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate// in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.Position Position::upstream() const{    Node* startNode = node();    if (!startNode)        return Position();        // iterate backward from there, looking for a qualified position    Node* boundary = enclosingVisualBoundary(startNode);    PositionIterator lastVisible = *this;    PositionIterator currentPos = lastVisible;    bool startEditable = startNode->isContentEditable();

⌨️ 快捷键说明

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