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

📄 range.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec){    RefPtr<Node> newParent = passNewParent;    if (!m_start.container()) {        ec = INVALID_STATE_ERR;        return;    }    if (!newParent) {        ec = NOT_FOUND_ERR;        return;    }    // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,    // Document, or DocumentFragment node.    switch (newParent->nodeType()) {        case Node::ATTRIBUTE_NODE:        case Node::DOCUMENT_FRAGMENT_NODE:        case Node::DOCUMENT_NODE:        case Node::DOCUMENT_TYPE_NODE:        case Node::ENTITY_NODE:        case Node::NOTATION_NODE:            ec = RangeException::INVALID_NODE_TYPE_ERR;            return;        case Node::CDATA_SECTION_NODE:        case Node::COMMENT_NODE:        case Node::ELEMENT_NODE:        case Node::ENTITY_REFERENCE_NODE:        case Node::PROCESSING_INSTRUCTION_NODE:        case Node::TEXT_NODE:        case Node::XPATH_NAMESPACE_NODE:            break;    }    // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of    // the Range is read-only.    if (containedByReadOnly()) {        ec = NO_MODIFICATION_ALLOWED_ERR;        return;    }    // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were    // not created from the same document.    if (newParent->document() != m_start.container()->document()) {        ec = WRONG_DOCUMENT_ERR;        return;    }    // Raise a HIERARCHY_REQUEST_ERR if m_start.container() doesn't accept children like newParent.    Node* parentOfNewParent = m_start.container();    // If m_start.container() is a character data node, it will be split and it will be its parent that will     // need to accept newParent (or in the case of a comment, it logically "would" be inserted into the parent,    // although this will fail below for another reason).    if (parentOfNewParent->isCharacterDataNode())        parentOfNewParent = parentOfNewParent->parentNode();    if (!parentOfNewParent->childTypeAllowed(newParent->nodeType())) {        ec = HIERARCHY_REQUEST_ERR;        return;    }        if (m_start.container() == newParent || m_start.container()->isDescendantOf(newParent.get())) {        ec = HIERARCHY_REQUEST_ERR;        return;    }    // FIXME: Do we need a check if the node would end up with a child node of a type not    // allowed by the type of node?    // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text node.    Node* startNonTextContainer = m_start.container();    if (startNonTextContainer->nodeType() == Node::TEXT_NODE)        startNonTextContainer = startNonTextContainer->parentNode();    Node* endNonTextContainer = m_end.container();    if (endNonTextContainer->nodeType() == Node::TEXT_NODE)        endNonTextContainer = endNonTextContainer->parentNode();    if (startNonTextContainer != endNonTextContainer) {        ec = RangeException::BAD_BOUNDARYPOINTS_ERR;        return;    }    ec = 0;    while (Node* n = newParent->firstChild()) {        newParent->removeChild(n, ec);        if (ec)            return;    }    RefPtr<DocumentFragment> fragment = extractContents(ec);    if (ec)        return;    insertNode(newParent, ec);    if (ec)        return;    newParent->appendChild(fragment.release(), ec);    if (ec)        return;    selectNode(newParent.get(), ec);}void Range::setStartBefore(Node* refNode, ExceptionCode& ec){    if (!m_start.container()) {        ec = INVALID_STATE_ERR;        return;    }    if (!refNode) {        ec = NOT_FOUND_ERR;        return;    }    if (refNode->document() != m_ownerDocument) {        ec = WRONG_DOCUMENT_ERR;        return;    }    ec = 0;    checkNodeBA(refNode, ec);    if (ec)        return;    setStart(refNode->parentNode(), refNode->nodeIndex(), ec);}void Range::checkDeleteExtract(ExceptionCode& ec){    if (!m_start.container()) {        ec = INVALID_STATE_ERR;        return;    }    ec = 0;    if (!commonAncestorContainer(ec) || ec)        return;            Node* pastLast = pastLastNode();    for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) {        if (n->isReadOnlyNode()) {            ec = NO_MODIFICATION_ALLOWED_ERR;            return;        }        if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) {            ec = HIERARCHY_REQUEST_ERR;            return;        }    }    if (containedByReadOnly()) {        ec = NO_MODIFICATION_ALLOWED_ERR;        return;    }}bool Range::containedByReadOnly() const{    for (Node* n = m_start.container(); n; n = n->parentNode()) {        if (n->isReadOnlyNode())            return true;    }    for (Node* n = m_end.container(); n; n = n->parentNode()) {        if (n->isReadOnlyNode())            return true;    }    return false;}Node* Range::firstNode() const{    if (!m_start.container())        return 0;    if (m_start.container()->offsetInCharacters())        return m_start.container();    if (Node* child = m_start.container()->childNode(m_start.offset()))        return child;    if (!m_start.offset())        return m_start.container();    return m_start.container()->traverseNextSibling();}Position Range::editingStartPosition() const{    // This function is used by range style computations to avoid bugs like:    // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once    // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up     // with a spurious "mixed" style.        VisiblePosition visiblePosition(m_start.container(), m_start.offset(), VP_DEFAULT_AFFINITY);    if (visiblePosition.isNull())        return Position();    ExceptionCode ec = 0;    // if the selection is a caret, just return the position, since the style    // behind us is relevant    if (collapsed(ec))        return visiblePosition.deepEquivalent();    // if the selection starts just before a paragraph break, skip over it    if (isEndOfParagraph(visiblePosition))        return visiblePosition.next().deepEquivalent().downstream();    // otherwise, make sure to be at the start of the first selected node,    // instead of possibly at the end of the last node before the selection    return visiblePosition.deepEquivalent().downstream();}Node* Range::shadowTreeRootNode() const{    return startContainer() ? startContainer()->shadowTreeRootNode() : 0;}Node* Range::pastLastNode() const{    if (!m_start.container() || !m_end.container())        return 0;    if (m_end.container()->offsetInCharacters())        return m_end.container()->traverseNextSibling();    if (Node* child = m_end.container()->childNode(m_end.offset()))        return child;    return m_end.container()->traverseNextSibling();}IntRect Range::boundingBox(){    IntRect result;    Vector<IntRect> rects;    addLineBoxRects(rects);    const size_t n = rects.size();    for (size_t i = 0; i < n; ++i)        result.unite(rects[i]);    return result;}void Range::addLineBoxRects(Vector<IntRect>& rects, bool useSelectionHeight){    if (!m_start.container() || !m_end.container())        return;    RenderObject* start = m_start.container()->renderer();    RenderObject* end = m_end.container()->renderer();    if (!start || !end)        return;    RenderObject* stop = end->nextInPreOrderAfterChildren();    for (RenderObject* r = start; r && r != stop; r = r->nextInPreOrder()) {        // only ask leaf render objects for their line box rects        if (!r->firstChild()) {            int startOffset = r == start ? m_start.offset() : 0;            int endOffset = r == end ? m_end.offset() : INT_MAX;            r->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight);        }    }}#ifndef NDEBUG#define FormatBufferSize 1024void Range::formatForDebugger(char* buffer, unsigned length) const{    String result;    String s;        if (!m_start.container() || !m_end.container())        result = "<empty>";    else {        char s[FormatBufferSize];        result += "from offset ";        result += String::number(m_start.offset());        result += " of ";        m_start.container()->formatForDebugger(s, FormatBufferSize);        result += s;        result += " to offset ";        result += String::number(m_end.offset());        result += " of ";        m_end.container()->formatForDebugger(s, FormatBufferSize);        result += s;    }              strncpy(buffer, result.utf8().data(), length - 1);}#undef FormatBufferSize#endifbool operator==(const Range& a, const Range& b){    if (&a == &b)        return true;    // Not strictly legal C++, but in practice this can happen, and this check works    // fine with GCC to detect such cases and return false rather than crashing.    if (!&a || !&b)        return false;    return a.startPosition() == b.startPosition() && a.endPosition() == b.endPosition();}PassRefPtr<Range> rangeOfContents(Node* node){    ASSERT(node);    RefPtr<Range> range = Range::create(node->document());    int exception = 0;    range->selectNodeContents(node, exception);    return range.release();}int Range::maxStartOffset() const{    if (!m_start.container())        return 0;    if (!m_start.container()->offsetInCharacters())        return m_start.container()->childNodeCount();    return m_start.container()->maxCharacterOffset();}int Range::maxEndOffset() const{    if (!m_end.container())        return 0;    if (!m_end.container()->offsetInCharacters())        return m_end.container()->childNodeCount();    return m_end.container()->maxCharacterOffset();}static inline void boundaryNodeChildrenChanged(RangeBoundaryPoint& boundary, ContainerNode* container){    if (!boundary.childBefore())        return;    if (boundary.container() != container)        return;    boundary.invalidateOffset();}void Range::nodeChildrenChanged(ContainerNode* container){    ASSERT(container);    ASSERT(container->document() == m_ownerDocument);    boundaryNodeChildrenChanged(m_start, container);    boundaryNodeChildrenChanged(m_end, container);}static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved){    if (boundary.childBefore() == nodeToBeRemoved) {        boundary.childBeforeWillBeRemoved();        return;    }    for (Node* n = boundary.container(); n; n = n->parentNode()) {        if (n == nodeToBeRemoved) {            boundary.setToChild(nodeToBeRemoved);            return;        }    }}void Range::nodeWillBeRemoved(Node* node){    ASSERT(node);    ASSERT(node->document() == m_ownerDocument);    ASSERT(node != m_ownerDocument);    ASSERT(node->parentNode());    boundaryNodeWillBeRemoved(m_start, node);    boundaryNodeWillBeRemoved(m_end, node);}static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length){    if (boundary.container() != text)        return;    unsigned boundaryOffset = boundary.offset();    if (offset >= boundaryOffset)        return;    boundary.setOffset(boundaryOffset + length);}void Range::textInserted(Node* text, unsigned offset, unsigned length){    ASSERT(text);    ASSERT(text->document() == m_ownerDocument);    boundaryTextInserted(m_start, text, offset, length);    boundaryTextInserted(m_end, text, offset, length);}static inline void boundaryTextRemoved(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length){    if (boundary.container() != text)        return;    unsigned boundaryOffset = boundary.offset();    if (offset >= boundaryOffset)        return;    if (offset + length >= boundaryOffset)        boundary.setOffset(offset);    else        boundary.setOffset(boundaryOffset - length);}void Range::textRemoved(Node* text, unsigned offset, unsigned length){    ASSERT(text);    ASSERT(text->document() == m_ownerDocument);    boundaryTextRemoved(m_start, text, offset, length);    boundaryTextRemoved(m_end, text, offset, length);}static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset){    if (boundary.container() == oldNode.node())        boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);    else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())        boundary.set(oldNode.node()->previousSibling(), offset, 0);}void Range::textNodesMerged(NodeWithIndex& oldNode, unsigned offset){    ASSERT(oldNode.node());    ASSERT(oldNode.node()->document() == m_ownerDocument);    ASSERT(oldNode.node()->parentNode());    ASSERT(oldNode.node()->isTextNode());    ASSERT(oldNode.node()->previousSibling());    ASSERT(oldNode.node()->previousSibling()->isTextNode());    boundaryTextNodesMerged(m_start, oldNode, offset);    boundaryTextNodesMerged(m_end, oldNode, offset);}static inline void boundaryTextNodesSplit(RangeBoundaryPoint& boundary, Text* oldNode){    if (boundary.container() != oldNode)        return;    unsigned boundaryOffset = boundary.offset();    if (boundaryOffset <= oldNode->length())        return;    boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);}void Range::textNodeSplit(Text* oldNode){    ASSERT(oldNode);    ASSERT(oldNode->document() == m_ownerDocument);    ASSERT(oldNode->parentNode());    ASSERT(oldNode->isTextNode());    ASSERT(oldNode->nextSibling());    ASSERT(oldNode->nextSibling()->isTextNode());    boundaryTextNodesSplit(m_start, oldNode);    boundaryTextNodesSplit(m_end, oldNode);}}

⌨️ 快捷键说明

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