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

📄 deleteselectioncommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // typing style at the start of the selection, nor is there a reason to     // compute the style at the start of the selection after deletion (see the     // early return in calculateTypingStyleAfterDelete).    if (m_upstreamStart.node() == m_downstreamEnd.node() && m_upstreamStart.node()->isTextNode())        return;            // Figure out the typing style in effect before the delete is done.    RefPtr<CSSComputedStyleDeclaration> computedStyle = positionBeforeTabSpan(m_selectionToDelete.start()).computedStyle();    m_typingStyle = computedStyle->copyInheritableProperties();        removeEnclosingAnchorStyle(m_typingStyle.get(), m_selectionToDelete.start());        // If we're deleting into a Mail blockquote, save the style at end() instead of start()    // We'll use this later in computeTypingStyleAfterDelete if we end up outside of a Mail blockquote    if (nearestMailBlockquote(m_selectionToDelete.start().node())) {        computedStyle = m_selectionToDelete.end().computedStyle();        m_deleteIntoBlockquoteStyle = computedStyle->copyInheritableProperties();    } else        m_deleteIntoBlockquoteStyle = 0;}bool DeleteSelectionCommand::handleSpecialCaseBRDelete(){    // Check for special-case where the selection contains only a BR on a line by itself after another BR.    bool upstreamStartIsBR = m_upstreamStart.node()->hasTagName(brTag);    bool downstreamStartIsBR = m_downstreamStart.node()->hasTagName(brTag);    bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && m_downstreamStart.node() == m_upstreamEnd.node();    if (isBROnLineByItself) {        removeNode(m_downstreamStart.node());        return true;    }    // Not a special-case delete per se, but we can detect that the merging of content between blocks    // should not be done.    if (upstreamStartIsBR && downstreamStartIsBR) {        m_mergeBlocksAfterDelete = false;        m_endingPosition = m_downstreamEnd;    }        return false;}static void updatePositionForNodeRemoval(Node* node, Position& position){    if (position.isNull())        return;    if (node->parent() == position.node() && node->nodeIndex() < (unsigned)position.offset())        position = Position(position.node(), position.offset() - 1);    if (position.node() == node || position.node()->isDescendantOf(node))        position = positionBeforeNode(node);}void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node){    if (!node)        return;            if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) && node->isDescendantOf(m_endRoot.get()))) {        // If a node is not in both the start and end editable roots, remove it only if its inside an editable region.        if (!node->parentNode()->isContentEditable()) {            // Don't remove non-editable atomic nodes.            if (!node->firstChild())                return;            // Search this non-editable region for editable regions to empty.            RefPtr<Node> child = node->firstChild();            while (child) {                RefPtr<Node> nextChild = child->nextSibling();                removeNode(child.get());                // Bail if nextChild is no longer node's child.                if (nextChild && nextChild->parentNode() != node)                    return;                child = nextChild;            }                        // Don't remove editable regions that are inside non-editable ones, just clear them.            return;        }    }        if (isTableStructureNode(node.get()) || node == node->rootEditableElement()) {        // Do not remove an element of table structure; remove its contents.        // Likewise for the root editable element.        Node* child = node->firstChild();        while (child) {            Node* remove = child;            child = child->nextSibling();            removeNode(remove);        }                // make sure empty cell has some height        updateLayout();        RenderObject *r = node->renderer();        if (r && r->isTableCell() && static_cast<RenderTableCell*>(r)->contentHeight() <= 0)            insertBlockPlaceholder(Position(node,0));        return;    }        if (node == m_startBlock && !isEndOfBlock(VisiblePosition(m_startBlock.get(), 0, DOWNSTREAM).previous()))        m_needPlaceholder = true;    else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(m_endBlock.get(), maxDeepOffset(m_endBlock.get()), DOWNSTREAM).next()))        m_needPlaceholder = true;        // FIXME: Update the endpoints of the range being deleted.    updatePositionForNodeRemoval(node.get(), m_endingPosition);    updatePositionForNodeRemoval(node.get(), m_leadingWhitespace);    updatePositionForNodeRemoval(node.get(), m_trailingWhitespace);        CompositeEditCommand::removeNode(node);}static void updatePositionForTextRemoval(Node* node, int offset, int count, Position& position){    if (position.node() == node) {        if (position.offset() > offset + count)            position = Position(position.node(), position.offset() - count);        else if (position.offset() > offset)            position = Position(position.node(), offset);    }}void DeleteSelectionCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count){    // FIXME: Update the endpoints of the range being deleted.    updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition);    updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace);    updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace);        CompositeEditCommand::deleteTextFromNode(node, offset, count);}void DeleteSelectionCommand::handleGeneralDelete(){    int startOffset = m_upstreamStart.offset();    Node* startNode = m_upstreamStart.node();        // Never remove the start block unless it's a table, in which case we won't merge content in.    if (startNode == m_startBlock && startOffset == 0 && canHaveChildrenForEditing(startNode) && !startNode->hasTagName(tableTag)) {        startOffset = 0;        startNode = startNode->traverseNextNode();    }    if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) {        Text *text = static_cast<Text *>(startNode);        if (text->length() > (unsigned)caretMaxOffset(startNode))            deleteTextFromNode(text, caretMaxOffset(startNode), text->length() - caretMaxOffset(startNode));    }    if (startOffset >= maxDeepOffset(startNode)) {        startNode = startNode->traverseNextSibling();        startOffset = 0;    }    // Done adjusting the start.  See if we're all done.    if (!startNode)        return;    if (startNode == m_downstreamEnd.node()) {        // The selection to delete is all in one node.        if (!startNode->renderer() ||             (startOffset == 0 && m_downstreamEnd.offset() >= maxDeepOffset(startNode))) {            // just delete            removeNode(startNode);        } else if (m_downstreamEnd.offset() - startOffset > 0) {            if (startNode->isTextNode()) {                // in a text node that needs to be trimmed                Text *text = static_cast<Text *>(startNode);                deleteTextFromNode(text, startOffset, m_downstreamEnd.offset() - startOffset);            } else {                removeChildrenInRange(startNode, startOffset, m_downstreamEnd.offset());                m_endingPosition = m_upstreamStart;            }        }    }    else {        bool startNodeWasDescendantOfEndNode = m_upstreamStart.node()->isDescendantOf(m_downstreamEnd.node());        // The selection to delete spans more than one node.        RefPtr<Node> node(startNode);                if (startOffset > 0) {            if (startNode->isTextNode()) {                // in a text node that needs to be trimmed                Text *text = static_cast<Text *>(node.get());                deleteTextFromNode(text, startOffset, text->length() - startOffset);                node = node->traverseNextNode();            } else {                node = startNode->childNode(startOffset);            }        }                // handle deleting all nodes that are completely selected        while (node && node != m_downstreamEnd.node()) {            if (Range::compareBoundaryPoints(Position(node.get(), 0), m_downstreamEnd) >= 0) {                // traverseNextSibling just blew past the end position, so stop deleting                node = 0;            } else if (!m_downstreamEnd.node()->isDescendantOf(node.get())) {                RefPtr<Node> nextNode = node->traverseNextSibling();                // if we just removed a node from the end container, update end position so the                // check above will work                if (node->parentNode() == m_downstreamEnd.node()) {                    ASSERT(node->nodeIndex() < (unsigned)m_downstreamEnd.offset());                    m_downstreamEnd = Position(m_downstreamEnd.node(), m_downstreamEnd.offset() - 1);                }                removeNode(node.get());                node = nextNode.get();            } else {                Node* n = node->lastDescendant();                if (m_downstreamEnd.node() == n && m_downstreamEnd.offset() >= caretMaxOffset(n)) {                    removeNode(node.get());                    node = 0;                } else                    node = node->traverseNextNode();            }        }                if (m_downstreamEnd.node() != startNode && !m_upstreamStart.node()->isDescendantOf(m_downstreamEnd.node()) && m_downstreamEnd.node()->inDocument() && m_downstreamEnd.offset() >= caretMinOffset(m_downstreamEnd.node())) {            if (m_downstreamEnd.offset() >= maxDeepOffset(m_downstreamEnd.node()) && !canHaveChildrenForEditing(m_downstreamEnd.node())) {                // The node itself is fully selected, not just its contents.  Delete it.                removeNode(m_downstreamEnd.node());            } else {                if (m_downstreamEnd.node()->isTextNode()) {                    // in a text node that needs to be trimmed                    Text *text = static_cast<Text *>(m_downstreamEnd.node());                    if (m_downstreamEnd.offset() > 0) {                        deleteTextFromNode(text, 0, m_downstreamEnd.offset());                        m_downstreamEnd = Position(text, 0);                    }                // Remove children of m_downstreamEnd.node() that come after m_upstreamStart.                // Don't try to remove children if m_upstreamStart was inside m_downstreamEnd.node()                // and m_upstreamStart has been removed from the document, because then we don't                 // know how many children to remove.                // FIXME: Make m_upstreamStart a position we update as we remove content, then we can                // always know which children to remove.                } else if (!(startNodeWasDescendantOfEndNode && !m_upstreamStart.node()->inDocument())) {                    int offset = 0;                    if (m_upstreamStart.node()->isDescendantOf(m_downstreamEnd.node())) {                        Node *n = m_upstreamStart.node();                        while (n && n->parentNode() != m_downstreamEnd.node())                            n = n->parentNode();                        if (n)                            offset = n->nodeIndex() + 1;                    }                    removeChildrenInRange(m_downstreamEnd.node(), offset, m_downstreamEnd.offset());                    m_downstreamEnd = Position(m_downstreamEnd.node(), offset);                }            }        }    }}void DeleteSelectionCommand::fixupWhitespace(){    updateLayout();    // FIXME: isRenderedCharacter should be removed, and we should use VisiblePosition::characterAfter and VisiblePosition::characterBefore    if (m_leadingWhitespace.isNotNull() && !m_leadingWhitespace.isRenderedCharacter()) {        Text* textNode = static_cast<Text*>(m_leadingWhitespace.node());        ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace());        replaceTextInNode(textNode, m_leadingWhitespace.offset(), 1, nonBreakingSpaceString());    }    if (m_trailingWhitespace.isNotNull() && !m_trailingWhitespace.isRenderedCharacter()) {        Text* textNode = static_cast<Text*>(m_trailingWhitespace.node());        ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWhiteSpace());        replaceTextInNode(textNode, m_trailingWhitespace.offset(), 1, nonBreakingSpaceString());    }}// If a selection starts in one block and ends in another, we have to merge to bring content before the// start together with content after the end.void DeleteSelectionCommand::mergeParagraphs()

⌨️ 快捷键说明

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