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

📄 htmlediting.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2004, 2005, 2006, 2007 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 "htmlediting.h"#include "CharacterNames.h"#include "Document.h"#include "EditingText.h"#include "HTMLBRElement.h"#include "HTMLDivElement.h"#include "HTMLElementFactory.h"#include "HTMLInterchange.h"#include "HTMLLIElement.h"#include "HTMLNames.h"#include "HTMLOListElement.h"#include "HTMLUListElement.h"#include "PositionIterator.h"#include "RenderObject.h"#include "Range.h"#include "VisibleSelection.h"#include "Text.h"#include "TextIterator.h"#include "VisiblePosition.h"#include "visible_units.h"#include <wtf/StdLibExtras.h>#if ENABLE(WML)#include "WMLNames.h"#endifusing namespace std;namespace WebCore {using namespace HTMLNames;// Atomic means that the node has no children, or has children which are ignored for the// purposes of editing.bool isAtomicNode(const Node *node){    return node && (!node->hasChildNodes() || editingIgnoresContent(node));}// Returns true for nodes that either have no content, or have content that is ignored (skipped // over) while editing.  There are no VisiblePositions inside these nodes.bool editingIgnoresContent(const Node* node){    return !canHaveChildrenForEditing(node) && !node->isTextNode();}bool canHaveChildrenForEditing(const Node* node){    return !node->hasTagName(hrTag) &&           !node->hasTagName(brTag) &&           !node->hasTagName(imgTag) &&           !node->hasTagName(buttonTag) &&           !node->hasTagName(inputTag) &&           !node->hasTagName(textareaTag) &&           !node->hasTagName(objectTag) &&           !node->hasTagName(iframeTag) &&           !node->hasTagName(embedTag) &&           !node->hasTagName(appletTag) &&           !node->hasTagName(selectTag) &&#if ENABLE(WML)           !node->hasTagName(WMLNames::doTag) &&#endif           !node->isTextNode();}// Compare two positions, taking into account the possibility that one or both// could be inside a shadow tree. Only works for non-null values.int comparePositions(const Position& a, const Position& b){    Node* nodeA = a.node();    ASSERT(nodeA);    Node* nodeB = b.node();    ASSERT(nodeB);    int offsetA = a.offset();    int offsetB = b.offset();    Node* shadowAncestorA = nodeA->shadowAncestorNode();    if (shadowAncestorA == nodeA)        shadowAncestorA = 0;    Node* shadowAncestorB = nodeB->shadowAncestorNode();    if (shadowAncestorB == nodeB)        shadowAncestorB = 0;    int bias = 0;    if (shadowAncestorA != shadowAncestorB) {        if (shadowAncestorA) {            nodeA = shadowAncestorA;            offsetA = 0;            bias = 1;        }        if (shadowAncestorB) {            nodeB = shadowAncestorB;            offsetB = 0;            bias = -1;        }    }    int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);    return result ? result : bias;}Node* highestEditableRoot(const Position& position){    Node* node = position.node();    if (!node)        return 0;            Node* highestRoot = editableRootForPosition(position);    if (!highestRoot)        return 0;        node = highestRoot;    while (node) {        if (node->isContentEditable())            highestRoot = node;        if (node->hasTagName(bodyTag))            break;        node = node->parentNode();    }        return highestRoot;}Node* lowestEditableAncestor(Node* node){    if (!node)        return 0;        Node *lowestRoot = 0;    while (node) {        if (node->isContentEditable())            return node->rootEditableElement();        if (node->hasTagName(bodyTag))            break;        node = node->parentNode();    }        return lowestRoot;}bool isEditablePosition(const Position& p){    Node* node = p.node();    if (!node)        return false;            if (node->renderer() && node->renderer()->isTable())        node = node->parentNode();        return node->isContentEditable();}bool isRichlyEditablePosition(const Position& p){    Node* node = p.node();    if (!node)        return false;            if (node->renderer() && node->renderer()->isTable())        node = node->parentNode();        return node->isContentRichlyEditable();}Element* editableRootForPosition(const Position& p){    Node* node = p.node();    if (!node)        return 0;            if (node->renderer() && node->renderer()->isTable())        node = node->parentNode();        return node->rootEditableElement();}bool isContentEditable(const Node* node){    return node->isContentEditable();}Position nextCandidate(const Position& position){    PositionIterator p = position;    while (!p.atEnd()) {        p.increment();        if (p.isCandidate())            return p;    }    return Position();}Position nextVisuallyDistinctCandidate(const Position& position){    Position p = position;    Position downstreamStart = p.downstream();    while (!p.atEnd()) {        p = p.next(Character);        if (p.isCandidate() && p.downstream() != downstreamStart)            return p;    }    return Position();}Position previousCandidate(const Position& position){    PositionIterator p = position;    while (!p.atStart()) {        p.decrement();        if (p.isCandidate())            return p;    }    return Position();}Position previousVisuallyDistinctCandidate(const Position& position){    Position p = position;    Position downstreamStart = p.downstream();    while (!p.atStart()) {        p = p.previous(Character);        if (p.isCandidate() && p.downstream() != downstreamStart)            return p;    }    return Position();}VisiblePosition firstEditablePositionAfterPositionInRoot(const Position& position, Node* highestRoot){    // position falls before highestRoot.    if (comparePositions(position, Position(highestRoot, 0)) == -1 && highestRoot->isContentEditable())        return VisiblePosition(Position(highestRoot, 0));            Position p = position;        if (Node* shadowAncestor = p.node()->shadowAncestorNode())        if (shadowAncestor != p.node())            p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));        while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))        p = isAtomicNode(p.node()) ? positionAfterNode(p.node()) : nextVisuallyDistinctCandidate(p);        if (p.node() && !p.node()->isDescendantOf(highestRoot))        return VisiblePosition();        return VisiblePosition(p);}VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& position, Node* highestRoot){    // When position falls after highestRoot, the result is easy to compute.    if (comparePositions(position, Position(highestRoot, maxDeepOffset(highestRoot))) == 1)        return VisiblePosition(Position(highestRoot, maxDeepOffset(highestRoot)));            Position p = position;        if (Node* shadowAncestor = p.node()->shadowAncestorNode())        if (shadowAncestor != p.node())            p = Position(shadowAncestor, 0);        while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))        p = isAtomicNode(p.node()) ? positionBeforeNode(p.node()) : previousVisuallyDistinctCandidate(p);        if (p.node() && !p.node()->isDescendantOf(highestRoot))        return VisiblePosition();        return VisiblePosition(p);}// Whether or not content before and after this node will collapse onto the same line as it.bool isBlock(const Node* node){    return node && node->renderer() && !node->renderer()->isInline();}// FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.// FIXME: Pass a position to this function.  The enclosing block of [table, x] for example, should be the // block that contains the table and not the table, and this function should be the only one responsible for // knowing about these kinds of special cases.Node* enclosingBlock(Node* node){    return static_cast<Element*>(enclosingNodeOfType(Position(node, 0), isBlock));}// Internally editing uses "invalid" positions for historical reasons.  For// example, in <div><img /></div>, Editing might use (img, 1) for the position// after <img>, but we have to convert that to (div, 1) before handing the// position to a Range object.  Ideally all internal positions should// be "range compliant" for simplicity.Position rangeCompliantEquivalent(const Position& pos){    if (pos.isNull())        return Position();    Node* node = pos.node();    if (pos.offset() <= 0) {        if (node->parentNode() && (editingIgnoresContent(node) || isTableElement(node)))            return positionBeforeNode(node);        return Position(node, 0);    }    if (node->offsetInCharacters())        return Position(node, min(node->maxCharacterOffset(), pos.offset()));    int maxCompliantOffset = node->childNodeCount();    if (pos.offset() > maxCompliantOffset) {        if (node->parentNode())            return positionAfterNode(node);

⌨️ 快捷键说明

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