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

📄 visibleselection.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            VisiblePosition end = endOfLine(VisiblePosition(m_end, m_affinity));            // If the end of this line is at the end of a paragraph, include the space             // after the end of the line in the selection.            if (isEndOfParagraph(end)) {                VisiblePosition next = end.next();                if (next.isNotNull())                    end = next;            }            m_end = end.deepEquivalent();            break;        }        case LineBoundary:            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();            m_end = endOfLine(VisiblePosition(m_end, m_affinity)).deepEquivalent();            break;        case ParagraphGranularity: {            VisiblePosition pos(m_start, m_affinity);            if (isStartOfLine(pos) && isEndOfDocument(pos))                pos = pos.previous();            m_start = startOfParagraph(pos).deepEquivalent();            VisiblePosition visibleParagraphEnd = endOfParagraph(VisiblePosition(m_end, m_affinity));                        // Include the "paragraph break" (the space from the end of this paragraph to the start            // of the next one) in the selection.            VisiblePosition end(visibleParagraphEnd.next());                         if (Node* table = isFirstPositionAfterTable(end)) {                // The paragraph break after the last paragraph in the last cell of a block table ends                // at the start of the paragraph after the table, not at the position just after the table.                if (isBlock(table))                    end = end.next(true);                // There is no parargraph break after the last paragraph in the last cell of an inline table.                else                    end = visibleParagraphEnd;            }                         if (end.isNull())                end = visibleParagraphEnd;                            m_end = end.deepEquivalent();            break;        }        case DocumentBoundary:            m_start = startOfDocument(VisiblePosition(m_start, m_affinity)).deepEquivalent();            m_end = endOfDocument(VisiblePosition(m_end, m_affinity)).deepEquivalent();            break;        case ParagraphBoundary:            m_start = startOfParagraph(VisiblePosition(m_start, m_affinity)).deepEquivalent();            m_end = endOfParagraph(VisiblePosition(m_end, m_affinity)).deepEquivalent();            break;        case SentenceBoundary:            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();            break;    }        // Make sure we do not have a dangling start or end.    if (m_start.isNull())        m_start = m_end;    if (m_end.isNull())        m_end = m_start;}void VisibleSelection::updateSelectionType(){    if (m_start.isNull()) {        ASSERT(m_end.isNull());        m_selectionType = NoSelection;    } else if (m_start == m_end || m_start.upstream() == m_end.upstream()) {        m_selectionType = CaretSelection;    } else        m_selectionType = RangeSelection;    // Affinity only makes sense for a caret    if (m_selectionType != CaretSelection)        m_affinity = DOWNSTREAM;}void VisibleSelection::validate(){    setBaseAndExtentToDeepEquivalents();    setStartAndEndFromBaseAndExtentRespectingGranularity();    adjustSelectionToAvoidCrossingEditingBoundaries();    updateSelectionType();    if (selectionType() == RangeSelection) {        // "Constrain" the selection to be the smallest equivalent range of nodes.        // This is a somewhat arbitrary choice, but experience shows that it is        // useful to make to make the selection "canonical" (if only for        // purposes of comparing selections). This is an ideal point of the code        // to do this operation, since all selection changes that result in a RANGE         // come through here before anyone uses it.        // FIXME: Canonicalizing is good, but haven't we already done it (when we        // set these two positions to VisiblePosition deepEquivalent()s above)?        m_start = m_start.downstream();        m_end = m_end.upstream();    }}// FIXME: This function breaks the invariant of this class.// But because we use VisibleSelection to store values in editing commands for use when// undoing the command, we need to be able to create a selection that while currently// invalid, will be valid once the changes are undone. This is a design problem.// To fix it we either need to change the invariants of VisibleSelection or create a new// class for editing to use that can manipulate selections that are not currently valid.void VisibleSelection::setWithoutValidation(const Position& base, const Position& extent){    ASSERT(!base.isNull());    ASSERT(!extent.isNull());    ASSERT(base != extent);    ASSERT(m_affinity == DOWNSTREAM);    ASSERT(m_granularity == CharacterGranularity);    m_base = base;    m_extent = extent;    m_baseIsFirst = comparePositions(base, extent) <= 0;    if (m_baseIsFirst) {        m_start = base;        m_end = extent;    } else {        m_start = extent;        m_end = base;    }    m_selectionType = RangeSelection;}void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries(){    if (m_base.isNull() || m_start.isNull() || m_end.isNull())        return;    Node* baseRoot = highestEditableRoot(m_base);    Node* startRoot = highestEditableRoot(m_start);    Node* endRoot = highestEditableRoot(m_end);        Node* baseEditableAncestor = lowestEditableAncestor(m_base.node());        // The base, start and end are all in the same region.  No adjustment necessary.    if (baseRoot == startRoot && baseRoot == endRoot)        return;        // The selection is based in editable content.    if (baseRoot) {        // If the start is outside the base's editable root, cap it at the start of that root.        // If the start is in non-editable content that is inside the base's editable root, put it        // at the first editable position after start inside the base's editable root.        if (startRoot != baseRoot) {            VisiblePosition first = firstEditablePositionAfterPositionInRoot(m_start, baseRoot);            m_start = first.deepEquivalent();            if (m_start.isNull()) {                ASSERT_NOT_REACHED();                m_start = m_end;            }        }        // If the end is outside the base's editable root, cap it at the end of that root.        // If the end is in non-editable content that is inside the base's root, put it        // at the last editable position before the end inside the base's root.        if (endRoot != baseRoot) {            VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot);            m_end = last.deepEquivalent();            if (m_end.isNull()) {                ASSERT_NOT_REACHED();                m_end = m_start;            }        }    // The selection is based in non-editable content.    } else {        // FIXME: Non-editable pieces inside editable content should be atomic, in the same way that editable        // pieces in non-editable content are atomic.            // The selection ends in editable content or non-editable content inside a different editable ancestor,         // move backward until non-editable content inside the same lowest editable ancestor is reached.        Node* endEditableAncestor = lowestEditableAncestor(m_end.node());        if (endRoot || endEditableAncestor != baseEditableAncestor) {                        Position p = previousVisuallyDistinctCandidate(m_end);            Node* shadowAncestor = endRoot ? endRoot->shadowAncestorNode() : 0;            if (p.isNull() && endRoot && (shadowAncestor != endRoot))                p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));            while (p.isNotNull() && !(lowestEditableAncestor(p.node()) == baseEditableAncestor && !isEditablePosition(p))) {                Node* root = editableRootForPosition(p);                shadowAncestor = root ? root->shadowAncestorNode() : 0;                p = isAtomicNode(p.node()) ? positionBeforeNode(p.node()) : previousVisuallyDistinctCandidate(p);                if (p.isNull() && (shadowAncestor != root))                    p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));            }            VisiblePosition previous(p);            if (previous.isNull()) {                // The selection crosses an Editing boundary.  This is a                // programmer error in the editing code.  Happy debugging!                ASSERT_NOT_REACHED();                m_base = Position();                m_extent = Position();                validate();                return;            }            m_end = previous.deepEquivalent();        }        // The selection starts in editable content or non-editable content inside a different editable ancestor,         // move forward until non-editable content inside the same lowest editable ancestor is reached.        Node* startEditableAncestor = lowestEditableAncestor(m_start.node());              if (startRoot || startEditableAncestor != baseEditableAncestor) {            Position p = nextVisuallyDistinctCandidate(m_start);            Node* shadowAncestor = startRoot ? startRoot->shadowAncestorNode() : 0;            if (p.isNull() && startRoot && (shadowAncestor != startRoot))                p = Position(shadowAncestor, 0);            while (p.isNotNull() && !(lowestEditableAncestor(p.node()) == baseEditableAncestor && !isEditablePosition(p))) {                Node* root = editableRootForPosition(p);                shadowAncestor = root ? root->shadowAncestorNode() : 0;                p = isAtomicNode(p.node()) ? positionAfterNode(p.node()) : nextVisuallyDistinctCandidate(p);                if (p.isNull() && (shadowAncestor != root))                    p = Position(shadowAncestor, 0);            }            VisiblePosition next(p);                        if (next.isNull()) {                // The selection crosses an Editing boundary.  This is a                // programmer error in the editing code.  Happy debugging!                ASSERT_NOT_REACHED();                m_base = Position();                m_extent = Position();                validate();                return;            }            m_start = next.deepEquivalent();        }    }        // Correct the extent if necessary.    if (baseEditableAncestor != lowestEditableAncestor(m_extent.node()))        m_extent = m_baseIsFirst ? m_end : m_start;}bool VisibleSelection::isContentEditable() const{    return isEditablePosition(start());}bool VisibleSelection::isContentRichlyEditable() const{    return isRichlyEditablePosition(start());}Element* VisibleSelection::rootEditableElement() const{    return editableRootForPosition(start());}Node* VisibleSelection::shadowTreeRootNode() const{    return start().node() ? start().node()->shadowTreeRootNode() : 0;}void VisibleSelection::debugPosition() const{    if (!m_start.node())        return;    fprintf(stderr, "VisibleSelection =================\n");    if (m_start == m_end) {        Position pos = m_start;        fprintf(stderr, "pos:        %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset());    } else {        Position pos = m_start;        fprintf(stderr, "start:      %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset());        fprintf(stderr, "-----------------------------------\n");        pos = m_end;        fprintf(stderr, "end:        %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset());        fprintf(stderr, "-----------------------------------\n");    }    fprintf(stderr, "================================\n");}#ifndef NDEBUGvoid VisibleSelection::formatForDebugger(char* buffer, unsigned length) const{    String result;    String s;        if (isNone()) {        result = "<none>";    } else {        const int FormatBufferSize = 1024;        char s[FormatBufferSize];        result += "from ";        start().formatForDebugger(s, FormatBufferSize);        result += s;        result += " to ";        end().formatForDebugger(s, FormatBufferSize);        result += s;    }    strncpy(buffer, result.utf8().data(), length - 1);}void VisibleSelection::showTreeForThis() const{    if (start().node()) {        start().node()->showTreeAndMark(start().node(), "S", end().node(), "E");        fprintf(stderr, "start offset: %d, end offset: %d\n", start().offset(), end().offset());    }}#endif} // namespace WebCore#ifndef NDEBUGvoid showTree(const WebCore::VisibleSelection& sel){    sel.showTreeForThis();}void showTree(const WebCore::VisibleSelection* sel){    if (sel)        sel->showTreeForThis();}#endif

⌨️ 快捷键说明

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