Esempio n. 1
0
EditCommand::EditCommand(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection)
    : m_document(document)
{
    ASSERT(document.frame());
    setStartingSelection(startingSelection);
    setEndingSelection(endingSelection);
}
Esempio n. 2
0
EditCommand::EditCommand(Document& document)
    : m_document(&document), m_parent(nullptr) {
  DCHECK(m_document);
  DCHECK(m_document->frame());
  setStartingSelection(m_document->frame()->selection().selection());
  setEndingVisibleSelection(m_startingSelection);
}
Esempio n. 3
0
EditCommand::EditCommand(Document& document, EditAction editingAction)
    : m_document(document)
    , m_editingAction(editingAction)
{
    ASSERT(document.frame());
    setStartingSelection(m_document->frame()->selection().selection());
    setEndingSelection(m_startingSelection);
}
Esempio n. 4
0
EditCommand::EditCommand(Document* document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection)
    : m_document(document)
    , m_parent(nullptr)
{
    ASSERT(m_document);
    ASSERT(m_document->frame());
    setStartingSelection(startingSelection);
    setEndingSelection(endingSelection);
}
Esempio n. 5
0
EditCommand::EditCommand(Document& document)
    : m_document(&document)
    , m_parent(nullptr)
{
    ASSERT(m_document);
    ASSERT(m_document->frame());
    setStartingSelection(m_document->frame()->selection().selection());
    setEndingSelection(m_startingSelection);
}
Esempio n. 6
0
EditCommand::EditCommand(Document* document)
    : m_document(document)
    , m_parent(0)
{
    ASSERT(m_document);
    ASSERT(m_document->frame());
    setStartingSelection(avoidIntersectionWithNode(m_document->frame()->selection()->selection(), m_document->frame()->editor()->deleteButtonController()->containerElement()));
    setEndingSelection(m_startingSelection);
}
Esempio n. 7
0
void MoveSelectionCommand::doApply()
{
    ASSERT(endingSelection().isNonOrphanedRange());

    Position pos = m_position;
    if (pos.isNull())
        return;

    // Update the position otherwise it may become invalid after the selection is deleted.
    Position selectionEnd = endingSelection().end();
    if (pos.anchorType() == Position::PositionIsOffsetInAnchor && selectionEnd.anchorType() == Position::PositionIsOffsetInAnchor
        && selectionEnd.containerNode() == pos.containerNode() && selectionEnd.offsetInContainerNode() < pos.offsetInContainerNode()) {
        pos.moveToOffset(pos.offsetInContainerNode() - selectionEnd.offsetInContainerNode());

        Position selectionStart = endingSelection().start();
        if (selectionStart.anchorType() == Position::PositionIsOffsetInAnchor && selectionStart.containerNode() == pos.containerNode())
            pos.moveToOffset(pos.offsetInContainerNode() + selectionStart.offsetInContainerNode());
    }

    {
        auto deleteSelection = DeleteSelectionCommand::create(document(), m_smartDelete, true, false, true, true, EditActionDeleteByDrag);
        deleteSelection->setParent(this);
        deleteSelection->apply();
        m_commands.append(WTFMove(deleteSelection));
    }

    // If the node for the destination has been removed as a result of the deletion,
    // set the destination to the ending point after the deletion.
    // Fixes: <rdar://problem/3910425> REGRESSION (Mail): Crash in ReplaceSelectionCommand; 
    //        selection is empty, leading to null deref
    if (!pos.anchorNode()->inDocument())
        pos = endingSelection().start();

    cleanupAfterDeletion(pos);

    setEndingSelection(VisibleSelection(pos, endingSelection().affinity(), endingSelection().isDirectional()));
    setStartingSelection(endingSelection());
    if (!pos.anchorNode()->inDocument()) {
        // Document was modified out from under us.
        return;
    }
    ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
    if (m_smartInsert)
        options |= ReplaceSelectionCommand::SmartReplace;

    {
        auto replaceSelection = ReplaceSelectionCommand::create(document(), WTFMove(m_fragment), options, EditActionInsertFromDrop);
        replaceSelection->setParent(this);
        replaceSelection->apply();
        m_commands.append(WTFMove(replaceSelection));
    }
}
Esempio n. 8
0
void EditCommand::setStartingSelection(const VisiblePosition& position)
{
    setStartingSelection(VisibleSelection(position));
}
Esempio n. 9
0
void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity)
{
    Selection selectionToDelete;
    Selection selectionAfterUndo;

    switch (endingSelection().state()) {
        case Selection::RANGE:
            selectionToDelete = endingSelection();
            selectionAfterUndo = selectionToDelete;
            break;
        case Selection::CARET: {
            m_smartDelete = false;

            // Handle delete at beginning-of-block case.
            // Do nothing in the case that the caret is at the start of a
            // root editable element or at the start of a document.
            SelectionController selection;
            selection.setSelection(endingSelection());
            selection.modify(SelectionController::EXTEND, SelectionController::FORWARD, granularity);
            Position downstreamEnd = endingSelection().end().downstream();
            VisiblePosition visibleEnd = endingSelection().visibleEnd();
            if (visibleEnd == endOfParagraph(visibleEnd))
                downstreamEnd = visibleEnd.next(true).deepEquivalent().downstream();
            // When deleting tables: Select the table first, then perform the deletion
            if (downstreamEnd.node() && downstreamEnd.node()->renderer() && downstreamEnd.node()->renderer()->isTable() && downstreamEnd.offset() == 0) {
                setEndingSelection(Selection(endingSelection().end(), Position(downstreamEnd.node(), maxDeepOffset(downstreamEnd.node())), DOWNSTREAM));
                typingAddedToOpenCommand();
                return;
            }

            // deleting to end of paragraph when at end of paragraph needs to merge the next paragraph (if any)
            if (granularity == ParagraphBoundary && selection.selection().isCaret() && isEndOfParagraph(selection.selection().visibleEnd()))
                selection.modify(SelectionController::EXTEND, SelectionController::FORWARD, CharacterGranularity);

            selectionToDelete = selection.selection();
            if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start())
                selectionAfterUndo = selectionToDelete;
            else {
                // It's a little tricky to compute what the starting selection would have been in the original document.
                // We can't let the Selection class's validation kick in or it'll adjust for us based on
                // the current state of the document and we'll get the wrong result.
                Position extent = startingSelection().end();
                if (extent.node() != selectionToDelete.end().node())
                    extent = selectionToDelete.extent();
                else {
                    int extraCharacters;
                    if (selectionToDelete.start().node() == selectionToDelete.end().node())
                        extraCharacters = selectionToDelete.end().offset() - selectionToDelete.start().offset();
                    else
                        extraCharacters = selectionToDelete.end().offset();
                    extent = Position(extent.node(), extent.offset() + extraCharacters);
                }
                selectionAfterUndo.setWithoutValidation(startingSelection().start(), extent);
            }
            break;
        }
        case Selection::NONE:
            ASSERT_NOT_REACHED();
            break;
    }
    
    if (selectionToDelete.isCaretOrRange() && document()->frame()->shouldDeleteSelection(selectionToDelete)) {
        // make undo select what was deleted
        setStartingSelection(selectionAfterUndo);
        CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete);
        setSmartDelete(false);
        typingAddedToOpenCommand();
    }
}
Esempio n. 10
0
void TypingCommand::deleteKeyPressed(TextGranularity granularity)
{
    Selection selectionToDelete;
    Selection selectionAfterUndo;
    
    switch (endingSelection().state()) {
        case Selection::RANGE:
            selectionToDelete = endingSelection();
            selectionAfterUndo = selectionToDelete;
            break;
        case Selection::CARET: {
            m_smartDelete = false;

            SelectionController selection;
            selection.setSelection(endingSelection());
            selection.modify(SelectionController::EXTEND, SelectionController::BACKWARD, granularity);
            
            // When the caret is at the start of the editable area in an empty list item, break out of the list item.
            if (endingSelection().visibleStart().previous(true).isNull()) {
                if (breakOutOfEmptyListItem()) {
                    typingAddedToOpenCommand();
                    return;
                }
            }
            
            VisiblePosition visibleStart(endingSelection().visibleStart());
            // If the caret is at the start of a paragraph after a table, move content into the last table cell.
            if (isStartOfParagraph(visibleStart) && isFirstPositionAfterTable(visibleStart.previous(true))) {
                // Unless the caret is just before a table.  We don't want to move a table into the last table cell.
                if (isLastPositionBeforeTable(visibleStart))
                    return;
                // Extend the selection backward into the last cell, then deletion will handle the move.
                selection.modify(SelectionController::EXTEND, SelectionController::BACKWARD, granularity);
            // If the caret is just after a table, select the table and don't delete anything.
            } else if (Node* table = isFirstPositionAfterTable(visibleStart)) {
                setEndingSelection(Selection(Position(table, 0), endingSelection().start(), DOWNSTREAM));
                typingAddedToOpenCommand();
                return;
            }

            selectionToDelete = selection.selection();
            if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start())
                selectionAfterUndo = selectionToDelete;
            else
                // It's a little tricky to compute what the starting selection would have been in the original document.
                // We can't let the Selection class's validation kick in or it'll adjust for us based on
                // the current state of the document and we'll get the wrong result.
                selectionAfterUndo.setWithoutValidation(startingSelection().end(), selectionToDelete.extent());
            break;
        }
        case Selection::NONE:
            ASSERT_NOT_REACHED();
            break;
    }
    
    if (selectionToDelete.isCaretOrRange() && document()->frame()->shouldDeleteSelection(selectionToDelete)) {
        // Make undo select everything that has been deleted, unless an undo will undo more than just this deletion.
        // FIXME: This behaves like TextEdit except for the case where you open with text insertion and then delete
        // more text than you insert.  In that case all of the text that was around originally should be selected.
        if (m_openedByBackwardDelete)
            setStartingSelection(selectionAfterUndo);
        CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete);
        setSmartDelete(false);
        typingAddedToOpenCommand();
    }
}