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

📄 deleteselectioncommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2005 Apple Computer, 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 "DeleteSelectionCommand.h"#include "Document.h"#include "DocumentFragment.h"#include "Editor.h"#include "EditorClient.h"#include "Element.h"#include "Frame.h"#include "Logging.h"#include "CSSComputedStyleDeclaration.h"#include "htmlediting.h"#include "HTMLInputElement.h"#include "HTMLNames.h"#include "markup.h"#include "RenderTableCell.h"#include "ReplaceSelectionCommand.h"#include "Text.h"#include "TextIterator.h"#include "visible_units.h"namespace WebCore {using namespace HTMLNames;static bool isTableRow(const Node* node){    return node && node->hasTagName(trTag);}static bool isTableCellEmpty(Node* cell){    ASSERT(isTableCell(cell));    VisiblePosition firstInCell(Position(cell, 0));    VisiblePosition lastInCell(Position(cell, maxDeepOffset(cell)));    return firstInCell == lastInCell;}static bool isTableRowEmpty(Node* row){    if (!isTableRow(row))        return false;            for (Node* child = row->firstChild(); child; child = child->nextSibling())        if (isTableCell(child) && !isTableCellEmpty(child))            return false;        return true;}DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements)    : CompositeEditCommand(document),       m_hasSelectionToDelete(false),       m_smartDelete(smartDelete),       m_mergeBlocksAfterDelete(mergeBlocksAfterDelete),      m_replace(replace),      m_expandForSpecialElements(expandForSpecialElements),      m_pruneStartBlockIfNecessary(false),      m_startBlock(0),      m_endBlock(0),      m_typingStyle(0),      m_deleteIntoBlockquoteStyle(0){}DeleteSelectionCommand::DeleteSelectionCommand(const VisibleSelection& selection, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements)    : CompositeEditCommand(selection.start().node()->document()),       m_hasSelectionToDelete(true),       m_smartDelete(smartDelete),       m_mergeBlocksAfterDelete(mergeBlocksAfterDelete),      m_replace(replace),      m_expandForSpecialElements(expandForSpecialElements),      m_pruneStartBlockIfNecessary(false),      m_selectionToDelete(selection),      m_startBlock(0),      m_endBlock(0),      m_typingStyle(0),      m_deleteIntoBlockquoteStyle(0){}void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end){    Node* startSpecialContainer = 0;    Node* endSpecialContainer = 0;     start = m_selectionToDelete.start();    end = m_selectionToDelete.end();     // For HRs, we'll get a position at (HR,1) when hitting delete from the beginning of the previous line, or (HR,0) when forward deleting,    // but in these cases, we want to delete it, so manually expand the selection    if (start.node()->hasTagName(hrTag))        start = Position(start.node(), 0);    else if (end.node()->hasTagName(hrTag))        end = Position(end.node(), 1);        // FIXME: This is only used so that moveParagraphs can avoid the bugs in special element expanion.    if (!m_expandForSpecialElements)        return;        while (1) {        startSpecialContainer = 0;        endSpecialContainer = 0;            Position s = positionBeforeContainingSpecialElement(start, &startSpecialContainer);        Position e = positionAfterContainingSpecialElement(end, &endSpecialContainer);                if (!startSpecialContainer && !endSpecialContainer)            break;                    if (VisiblePosition(start) != m_selectionToDelete.visibleStart() || VisiblePosition(end) != m_selectionToDelete.visibleEnd())            break;                // If we're going to expand to include the startSpecialContainer, it must be fully selected.        if (startSpecialContainer && !endSpecialContainer && Range::compareBoundaryPoints(positionAfterNode(startSpecialContainer), end) > -1)            break;        // If we're going to expand to include the endSpecialContainer, it must be fully selected.                 if (endSpecialContainer && !startSpecialContainer && Range::compareBoundaryPoints(start, positionBeforeNode(endSpecialContainer)) > -1)            break;                if (startSpecialContainer && startSpecialContainer->isDescendantOf(endSpecialContainer))            // Don't adjust the end yet, it is the end of a special element that contains the start            // special element (which may or may not be fully selected).            start = s;        else if (endSpecialContainer && endSpecialContainer->isDescendantOf(startSpecialContainer))            // Don't adjust the start yet, it is the start of a special element that contains the end            // special element (which may or may not be fully selected).            end = e;        else {            start = s;            end = e;        }    }}void DeleteSelectionCommand::initializePositionData(){    Position start, end;    initializeStartEnd(start, end);        m_upstreamStart = start.upstream();    m_downstreamStart = start.downstream();    m_upstreamEnd = end.upstream();    m_downstreamEnd = end.downstream();        m_startRoot = editableRootForPosition(start);    m_endRoot = editableRootForPosition(end);        m_startTableRow = enclosingNodeOfType(start, &isTableRow);    m_endTableRow = enclosingNodeOfType(end, &isTableRow);        // Don't move content out of a table cell.    // If the cell is non-editable, enclosingNodeOfType won't return it by default, so    // tell that function that we don't care if it returns non-editable nodes.    Node* startCell = enclosingNodeOfType(m_upstreamStart, &isTableCell, false);    Node* endCell = enclosingNodeOfType(m_downstreamEnd, &isTableCell, false);    // FIXME: This isn't right.  A borderless table with two rows and a single column would appear as two paragraphs.    if (endCell && endCell != startCell)        m_mergeBlocksAfterDelete = false;        // Usually the start and the end of the selection to delete are pulled together as a result of the deletion.    // Sometimes they aren't (like when no merge is requested), so we must choose one position to hold the caret     // and receive the placeholder after deletion.    VisiblePosition visibleEnd(m_downstreamEnd);    if (m_mergeBlocksAfterDelete && !isEndOfParagraph(visibleEnd))        m_endingPosition = m_downstreamEnd;    else        m_endingPosition = m_downstreamStart;        // We don't want to merge into a block if it will mean changing the quote level of content after deleting     // selections that contain a whole number paragraphs plus a line break, since it is unclear to most users     // that such a selection actually ends at the start of the next paragraph. This matches TextEdit behavior     // for indented paragraphs.    if (numEnclosingMailBlockquotes(start) != numEnclosingMailBlockquotes(end) && isStartOfParagraph(visibleEnd) && isStartOfParagraph(VisiblePosition(start))) {        m_mergeBlocksAfterDelete = false;        m_pruneStartBlockIfNecessary = true;    }    // Handle leading and trailing whitespace, as well as smart delete adjustments to the selection    m_leadingWhitespace = m_upstreamStart.leadingWhitespacePosition(m_selectionToDelete.affinity());    m_trailingWhitespace = m_downstreamEnd.trailingWhitespacePosition(VP_DEFAULT_AFFINITY);    if (m_smartDelete) {            // skip smart delete if the selection to delete already starts or ends with whitespace        Position pos = VisiblePosition(m_upstreamStart, m_selectionToDelete.affinity()).deepEquivalent();        bool skipSmartDelete = pos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNotNull();        if (!skipSmartDelete)            skipSmartDelete = m_downstreamEnd.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNotNull();        // extend selection upstream if there is whitespace there        bool hasLeadingWhitespaceBeforeAdjustment = m_upstreamStart.leadingWhitespacePosition(m_selectionToDelete.affinity(), true).isNotNull();        if (!skipSmartDelete && hasLeadingWhitespaceBeforeAdjustment) {            VisiblePosition visiblePos = VisiblePosition(m_upstreamStart, VP_DEFAULT_AFFINITY).previous();            pos = visiblePos.deepEquivalent();            // Expand out one character upstream for smart delete and recalculate            // positions based on this change.            m_upstreamStart = pos.upstream();            m_downstreamStart = pos.downstream();            m_leadingWhitespace = m_upstreamStart.leadingWhitespacePosition(visiblePos.affinity());        }                // trailing whitespace is only considered for smart delete if there is no leading        // whitespace, as in the case where you double-click the first word of a paragraph.        if (!skipSmartDelete && !hasLeadingWhitespaceBeforeAdjustment && m_downstreamEnd.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNotNull()) {            // Expand out one character downstream for smart delete and recalculate            // positions based on this change.            pos = VisiblePosition(m_downstreamEnd, VP_DEFAULT_AFFINITY).next().deepEquivalent();            m_upstreamEnd = pos.upstream();            m_downstreamEnd = pos.downstream();            m_trailingWhitespace = m_downstreamEnd.trailingWhitespacePosition(VP_DEFAULT_AFFINITY);        }    }        // We must pass the positions through rangeCompliantEquivalent, since some editing positions    // that appear inside their nodes aren't really inside them.  [hr, 0] is one example.    // FIXME: rangeComplaintEquivalent should eventually be moved into enclosing element getters    // like the one below, since editing functions should obviously accept editing positions.    // FIXME: Passing false to enclosingNodeOfType tells it that it's OK to return a non-editable    // node.  This was done to match existing behavior, but it seems wrong.    m_startBlock = enclosingNodeOfType(rangeCompliantEquivalent(m_downstreamStart), &isBlock, false);    m_endBlock = enclosingNodeOfType(rangeCompliantEquivalent(m_upstreamEnd), &isBlock, false);}static void removeEnclosingAnchorStyle(CSSMutableStyleDeclaration* style, const Position& position){    Node* enclosingAnchor = enclosingAnchorElement(position);    if (!enclosingAnchor || !enclosingAnchor->parentNode())        return;                RefPtr<CSSMutableStyleDeclaration> parentStyle = Position(enclosingAnchor->parentNode(), 0).computedStyle()->copyInheritableProperties();    RefPtr<CSSMutableStyleDeclaration> anchorStyle = Position(enclosingAnchor, 0).computedStyle()->copyInheritableProperties();    parentStyle->diff(anchorStyle.get());    anchorStyle->diff(style);}void DeleteSelectionCommand::saveTypingStyleState(){    // A common case is deleting characters that are all from the same text node. In     // that case, the style at the start of the selection before deletion will be the     // same as the style at the start of the selection after deletion (since those    // two positions will be identical). Therefore there is no need to save the

⌨️ 快捷键说明

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