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

📄 replaceselectioncommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    // Paste at start or end of link goes outside of link.    insertionPos = positionAvoidingSpecialElementBoundary(insertionPos);        // FIXME: Can this wait until after the operation has been performed?  There doesn't seem to be    // any work performed after this that queries or uses the typing style.    if (Frame* frame = document()->frame())        frame->clearTypingStyle();        bool handledStyleSpans = handleStyleSpansBeforeInsertion(fragment, insertionPos);        // We're finished if there is nothing to add.    if (fragment.isEmpty() || !fragment.firstChild())        return;        // 1) Insert the content.    // 2) Remove redundant styles and style tags, this inner <b> for example: <b>foo <b>bar</b> baz</b>.    // 3) Merge the start of the added content with the content before the position being pasted into.    // 4) Do one of the following: a) expand the last br if the fragment ends with one and it collapsed,    // b) merge the last paragraph of the incoming fragment with the paragraph that contained the     // end of the selection that was pasted into, or c) handle an interchange newline at the end of the     // incoming fragment.    // 5) Add spaces for smart replace.    // 6) Select the replacement if requested, and match style if requested.        VisiblePosition startOfInsertedContent, endOfInsertedContent;        RefPtr<Node> refNode = fragment.firstChild();    RefPtr<Node> node = refNode->nextSibling();        fragment.removeNode(refNode);    insertNodeAtAndUpdateNodesInserted(refNode, insertionPos);        while (node) {        Node* next = node->nextSibling();        fragment.removeNode(node);        insertNodeAfterAndUpdateNodesInserted(node, refNode.get());        refNode = node;        node = next;    }        removeUnrenderedTextNodesAtEnds();        negateStyleRulesThatAffectAppearance();        if (!handledStyleSpans)        handleStyleSpans();        // Mutation events (bug 20161) may have already removed the inserted content    if (!m_firstNodeInserted || !m_firstNodeInserted->inDocument())        return;        endOfInsertedContent = positionAtEndOfInsertedContent();    startOfInsertedContent = positionAtStartOfInsertedContent();        // We inserted before the startBlock to prevent nesting, and the content before the startBlock wasn't in its own block and    // didn't have a br after it, so the inserted content ended up in the same paragraph.    if (startBlock && insertionPos.node() == startBlock->parentNode() && (unsigned)insertionPos.offset() < startBlock->nodeIndex() && !isStartOfParagraph(startOfInsertedContent))        insertNodeAt(createBreakElement(document()).get(), startOfInsertedContent.deepEquivalent());        Position lastPositionToSelect;        bool interchangeNewlineAtEnd = fragment.hasInterchangeNewlineAtEnd();    if (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR))        removeNodeAndPruneAncestors(endBR);        // Determine whether or not we should merge the end of inserted content with what's after it before we do    // the start merge so that the start merge doesn't effect our decision.    m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph);        if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart())) {        // Bail to avoid infinite recursion.        if (m_movingParagraph) {            // setting display:inline does not work for td elements in quirks mode            ASSERT(m_firstNodeInserted->hasTagName(tdTag));            return;        }        VisiblePosition destination = startOfInsertedContent.previous();        VisiblePosition startOfParagraphToMove = startOfInsertedContent;                // Merging the the first paragraph of inserted content with the content that came        // before the selection that was pasted into would also move content after         // the selection that was pasted into if: only one paragraph was being pasted,         // and it was not wrapped in a block, the selection that was pasted into ended         // at the end of a block and the next paragraph didn't start at the start of a block.        // Insert a line break just after the inserted content to separate it from what         // comes after and prevent that from happening.        VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent();        if (startOfParagraph(endOfInsertedContent) == startOfParagraphToMove)            insertNodeAt(createBreakElement(document()).get(), endOfInsertedContent.deepEquivalent());                // FIXME: Maintain positions for the start and end of inserted content instead of keeping nodes.  The nodes are        // only ever used to create positions where inserted content starts/ends.        moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove), destination);        m_firstNodeInserted = endingSelection().visibleStart().deepEquivalent().downstream().node();        if (!m_lastLeafInserted->inDocument())            m_lastLeafInserted = endingSelection().visibleEnd().deepEquivalent().upstream().node();    }                endOfInsertedContent = positionAtEndOfInsertedContent();    startOfInsertedContent = positionAtStartOfInsertedContent();        if (interchangeNewlineAtEnd) {        VisiblePosition next = endOfInsertedContent.next(true);        if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedContent) || next.isNull()) {            if (!isStartOfParagraph(endOfInsertedContent)) {                setEndingSelection(endOfInsertedContent);                // Use a default paragraph element (a plain div) for the empty paragraph, using the last paragraph                // block's style seems to annoy users.                insertParagraphSeparator(true);                // Select up to the paragraph separator that was added.                lastPositionToSelect = endingSelection().visibleStart().deepEquivalent();                updateNodesInserted(lastPositionToSelect.node());            }        } else {            // Select up to the beginning of the next paragraph.            lastPositionToSelect = next.deepEquivalent().downstream();        }            } else        mergeEndIfNeeded();        handlePasteAsQuotationNode();        endOfInsertedContent = positionAtEndOfInsertedContent();    startOfInsertedContent = positionAtStartOfInsertedContent();        // Add spaces for smart replace.    if (m_smartReplace && currentRoot) {        // Disable smart replace for password fields.        Node* start = currentRoot->shadowAncestorNode();        if (start->hasTagName(inputTag) && static_cast<HTMLInputElement*>(start)->inputType() == HTMLInputElement::PASSWORD)            m_smartReplace = false;    }    if (m_smartReplace) {        bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) &&                                  !isCharacterSmartReplaceExempt(endOfInsertedContent.characterAfter(), false);        if (needsTrailingSpace) {            RenderObject* renderer = m_lastLeafInserted->renderer();            bool collapseWhiteSpace = !renderer || renderer->style()->collapseWhiteSpace();            Node* endNode = positionAtEndOfInsertedContent().deepEquivalent().upstream().node();            if (endNode->isTextNode()) {                Text* text = static_cast<Text*>(endNode);                insertTextIntoNode(text, text->length(), collapseWhiteSpace ? nonBreakingSpaceString() : " ");            } else {                RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " ");                insertNodeAfterAndUpdateNodesInserted(node, endNode);            }        }            bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) &&                                 !isCharacterSmartReplaceExempt(startOfInsertedContent.previous().characterAfter(), true);        if (needsLeadingSpace) {            RenderObject* renderer = m_lastLeafInserted->renderer();            bool collapseWhiteSpace = !renderer || renderer->style()->collapseWhiteSpace();            Node* startNode = positionAtStartOfInsertedContent().deepEquivalent().downstream().node();            if (startNode->isTextNode()) {                Text* text = static_cast<Text*>(startNode);                insertTextIntoNode(text, 0, collapseWhiteSpace ? nonBreakingSpaceString() : " ");            } else {                RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " ");                // Don't updateNodesInserted.  Doing so would set m_lastLeafInserted to be the node containing the                 // leading space, but m_lastLeafInserted is supposed to mark the end of pasted content.                insertNodeBefore(node, startNode);                // FIXME: Use positions to track the start/end of inserted content.                m_firstNodeInserted = node;            }        }    }        completeHTMLReplacement(lastPositionToSelect);}bool ReplaceSelectionCommand::shouldRemoveEndBR(Node* endBR, const VisiblePosition& originalVisPosBeforeEndBR){    if (!endBR || !endBR->inDocument())        return false;            VisiblePosition visiblePos(Position(endBR, 0));        // Don't remove the br if nothing was inserted.    if (visiblePos.previous() == originalVisPosBeforeEndBR)        return false;        // Remove the br if it is collapsed away and so is unnecessary.    if (!document()->inStrictMode() && isEndOfBlock(visiblePos) && !isStartOfParagraph(visiblePos))        return true;            // A br that was originally holding a line open should be displaced by inserted content or turned into a line break.    // A br that was originally acting as a line break should still be acting as a line break, not as a placeholder.    return isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos);}void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositionToSelect){    Position start;    Position end;    // FIXME: This should never not be the case.    if (m_firstNodeInserted && m_firstNodeInserted->inDocument() && m_lastLeafInserted && m_lastLeafInserted->inDocument()) {                start = positionAtStartOfInsertedContent().deepEquivalent();        end = positionAtEndOfInsertedContent().deepEquivalent();                // FIXME (11475): Remove this and require that the creator of the fragment to use nbsps.        rebalanceWhitespaceAt(start);        rebalanceWhitespaceAt(end);        if (m_matchStyle) {            ASSERT(m_insertionStyle);            applyStyle(m_insertionStyle.get(), start, end);        }                    if (lastPositionToSelect.isNotNull())            end = lastPositionToSelect;    } else if (lastPositionToSelect.isNotNull())        start = end = lastPositionToSelect;    else        return;        if (m_selectReplacement)        setEndingSelection(VisibleSelection(start, end, SEL_DEFAULT_AFFINITY));    else        setEndingSelection(VisibleSelection(end, SEL_DEFAULT_AFFINITY));}EditAction ReplaceSelectionCommand::editingAction() const{    return m_editAction;}void ReplaceSelectionCommand::insertNodeAfterAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild){    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed    insertNodeAfter(insertChild, refChild);    updateNodesInserted(nodeToUpdate);}void ReplaceSelectionCommand::insertNodeAtAndUpdateNodesInserted(PassRefPtr<Node> insertChild, const Position& p){    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed    insertNodeAt(insertChild, p);    updateNodesInserted(nodeToUpdate);}void ReplaceSelectionCommand::insertNodeBeforeAndUpdateNodesInserted(PassRefPtr<Node> insertChild, Node* refChild){    Node* nodeToUpdate = insertChild.get(); // insertChild will be cleared when passed    insertNodeBefore(insertChild, refChild);    updateNodesInserted(nodeToUpdate);}void ReplaceSelectionCommand::updateNodesInserted(Node *node){    if (!node)        return;    if (!m_firstNodeInserted)        m_firstNodeInserted = node;        if (node == m_lastLeafInserted)        return;        m_lastLeafInserted = node->lastDescendant();}} // namespace WebCore

⌨️ 快捷键说明

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