Index: Source/core/editing/TypingCommand.cpp |
diff --git a/Source/core/editing/TypingCommand.cpp b/Source/core/editing/TypingCommand.cpp |
deleted file mode 100644 |
index e338359f680fe80b31d5327f9eea68bdf030d722..0000000000000000000000000000000000000000 |
--- a/Source/core/editing/TypingCommand.cpp |
+++ /dev/null |
@@ -1,635 +0,0 @@ |
-/* |
- * Copyright (C) 2005, 2006, 2007, 2008 Apple 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 "core/editing/TypingCommand.h" |
- |
-#include "core/HTMLNames.h" |
-#include "core/dom/Document.h" |
-#include "core/dom/Element.h" |
-#include "core/dom/ElementTraversal.h" |
-#include "core/editing/BreakBlockquoteCommand.h" |
-#include "core/editing/EditingUtilities.h" |
-#include "core/editing/Editor.h" |
-#include "core/editing/FrameSelection.h" |
-#include "core/editing/InsertLineBreakCommand.h" |
-#include "core/editing/InsertParagraphSeparatorCommand.h" |
-#include "core/editing/InsertTextCommand.h" |
-#include "core/editing/VisiblePosition.h" |
-#include "core/editing/VisibleUnits.h" |
-#include "core/editing/spellcheck/SpellChecker.h" |
-#include "core/frame/LocalFrame.h" |
-#include "core/html/HTMLBRElement.h" |
-#include "core/layout/LayoutObject.h" |
- |
-namespace blink { |
- |
-using namespace HTMLNames; |
- |
-class TypingCommandLineOperation { |
- STACK_ALLOCATED(); |
-public: |
- TypingCommandLineOperation(TypingCommand* typingCommand, bool selectInsertedText, const String& text) |
- : m_typingCommand(typingCommand) |
- , m_selectInsertedText(selectInsertedText) |
- , m_text(text) |
- { } |
- |
- void operator()(size_t lineOffset, size_t lineLength, bool isLastLine) const |
- { |
- if (isLastLine) { |
- if (!lineOffset || lineLength > 0) |
- m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), m_selectInsertedText); |
- } else { |
- if (lineLength > 0) |
- m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), false); |
- m_typingCommand->insertParagraphSeparator(); |
- } |
- } |
- |
-private: |
- RawPtrWillBeMember<TypingCommand> m_typingCommand; |
- bool m_selectInsertedText; |
- const String& m_text; |
-}; |
- |
-TypingCommand::TypingCommand(Document& document, ETypingCommand commandType, const String &textToInsert, Options options, TextGranularity granularity, TextCompositionType compositionType) |
- : TextInsertionBaseCommand(document) |
- , m_commandType(commandType) |
- , m_textToInsert(textToInsert) |
- , m_openForMoreTyping(true) |
- , m_selectInsertedText(options & SelectInsertedText) |
- , m_smartDelete(options & SmartDelete) |
- , m_granularity(granularity) |
- , m_compositionType(compositionType) |
- , m_killRing(options & KillRing) |
- , m_openedByBackwardDelete(false) |
- , m_shouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator) |
- , m_shouldPreventSpellChecking(options & PreventSpellChecking) |
-{ |
- updatePreservesTypingStyle(m_commandType); |
-} |
- |
-void TypingCommand::deleteSelection(Document& document, Options options) |
-{ |
- LocalFrame* frame = document.frame(); |
- ASSERT(frame); |
- |
- if (!frame->selection().isRange()) |
- return; |
- |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) { |
- lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
- lastTypingCommand->deleteSelection(options & SmartDelete); |
- return; |
- } |
- |
- TypingCommand::create(document, DeleteSelection, "", options)->apply(); |
-} |
- |
-void TypingCommand::deleteKeyPressed(Document& document, Options options, TextGranularity granularity) |
-{ |
- if (granularity == CharacterGranularity) { |
- LocalFrame* frame = document.frame(); |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) { |
- // If the last typing command is not Delete, open a new typing command. |
- // We need to group continuous delete commands alone in a single typing command. |
- if (lastTypingCommand->commandTypeOfOpenCommand() == DeleteKey) { |
- updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame); |
- lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
- lastTypingCommand->deleteKeyPressed(granularity, options & KillRing); |
- return; |
- } |
- } |
- } |
- |
- TypingCommand::create(document, DeleteKey, "", options, granularity)->apply(); |
-} |
- |
-void TypingCommand::forwardDeleteKeyPressed(Document& document, Options options, TextGranularity granularity) |
-{ |
- // FIXME: Forward delete in TextEdit appears to open and close a new typing command. |
- if (granularity == CharacterGranularity) { |
- LocalFrame* frame = document.frame(); |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) { |
- updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame); |
- lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
- lastTypingCommand->forwardDeleteKeyPressed(granularity, options & KillRing); |
- return; |
- } |
- } |
- |
- TypingCommand::create(document, ForwardDeleteKey, "", options, granularity)->apply(); |
-} |
- |
-void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, LocalFrame* frame) |
-{ |
- ASSERT(frame); |
- VisibleSelection currentSelection = frame->selection().selection(); |
- if (VisibleSelection::InDOMTree::equalSelections(currentSelection, typingCommand->endingSelection())) |
- return; |
- |
- typingCommand->setStartingSelection(currentSelection); |
- typingCommand->setEndingSelection(currentSelection); |
-} |
- |
-void TypingCommand::insertText(Document& document, const String& text, Options options, TextCompositionType composition) |
-{ |
- LocalFrame* frame = document.frame(); |
- ASSERT(frame); |
- |
- if (!text.isEmpty()) |
- document.frame()->spellChecker().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0])); |
- |
- insertText(document, text, frame->selection().selection(), options, composition); |
-} |
- |
-// FIXME: We shouldn't need to take selectionForInsertion. It should be identical to FrameSelection's current selection. |
-void TypingCommand::insertText(Document& document, const String& text, const VisibleSelection& selectionForInsertion, Options options, TextCompositionType compositionType) |
-{ |
- RefPtrWillBeRawPtr<LocalFrame> frame = document.frame(); |
- ASSERT(frame); |
- |
- VisibleSelection currentSelection = frame->selection().selection(); |
- |
- String newText = dispatchBeforeTextInsertedEvent(text, selectionForInsertion, compositionType == TextCompositionUpdate); |
- |
- // Set the starting and ending selection appropriately if we are using a selection |
- // that is different from the current selection. In the future, we should change EditCommand |
- // to deal with custom selections in a general way that can be used by all of the commands. |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame.get())) { |
- if (!VisibleSelection::InDOMTree::equalSelections(lastTypingCommand->endingSelection(), selectionForInsertion)) { |
- lastTypingCommand->setStartingSelection(selectionForInsertion); |
- lastTypingCommand->setEndingSelection(selectionForInsertion); |
- } |
- |
- lastTypingCommand->setCompositionType(compositionType); |
- lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
- lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
- lastTypingCommand->insertText(newText, options & SelectInsertedText); |
- return; |
- } |
- |
- RefPtrWillBeRawPtr<TypingCommand> cmd = TypingCommand::create(document, InsertText, newText, options, compositionType); |
- applyTextInsertionCommand(frame.get(), cmd, selectionForInsertion, currentSelection); |
-} |
- |
-void TypingCommand::insertLineBreak(Document& document, Options options) |
-{ |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document.frame())) { |
- lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
- lastTypingCommand->insertLineBreak(); |
- return; |
- } |
- |
- TypingCommand::create(document, InsertLineBreak, "", options)->apply(); |
-} |
- |
-void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document) |
-{ |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document.frame())) { |
- lastTypingCommand->insertParagraphSeparatorInQuotedContent(); |
- return; |
- } |
- |
- TypingCommand::create(document, InsertParagraphSeparatorInQuotedContent)->apply(); |
-} |
- |
-void TypingCommand::insertParagraphSeparator(Document& document, Options options) |
-{ |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document.frame())) { |
- lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
- lastTypingCommand->insertParagraphSeparator(); |
- return; |
- } |
- |
- TypingCommand::create(document, InsertParagraphSeparator, "", options)->apply(); |
-} |
- |
-PassRefPtrWillBeRawPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(LocalFrame* frame) |
-{ |
- ASSERT(frame); |
- |
- RefPtrWillBeRawPtr<CompositeEditCommand> lastEditCommand = frame->editor().lastEditCommand(); |
- if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand.get())->isOpenForMoreTyping()) |
- return nullptr; |
- |
- return static_cast<TypingCommand*>(lastEditCommand.get()); |
-} |
- |
-void TypingCommand::closeTyping(LocalFrame* frame) |
-{ |
- if (RefPtrWillBeRawPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) |
- lastTypingCommand->closeTyping(); |
-} |
- |
-void TypingCommand::doApply() |
-{ |
- if (!endingSelection().isNonOrphanedCaretOrRange()) |
- return; |
- |
- if (m_commandType == DeleteKey) { |
- if (m_commands.isEmpty()) |
- m_openedByBackwardDelete = true; |
- } |
- |
- switch (m_commandType) { |
- case DeleteSelection: |
- deleteSelection(m_smartDelete); |
- return; |
- case DeleteKey: |
- deleteKeyPressed(m_granularity, m_killRing); |
- return; |
- case ForwardDeleteKey: |
- forwardDeleteKeyPressed(m_granularity, m_killRing); |
- return; |
- case InsertLineBreak: |
- insertLineBreak(); |
- return; |
- case InsertParagraphSeparator: |
- insertParagraphSeparator(); |
- return; |
- case InsertParagraphSeparatorInQuotedContent: |
- insertParagraphSeparatorInQuotedContent(); |
- return; |
- case InsertText: |
- insertText(m_textToInsert, m_selectInsertedText); |
- return; |
- } |
- |
- ASSERT_NOT_REACHED(); |
-} |
- |
-EditAction TypingCommand::editingAction() const |
-{ |
- return EditActionTyping; |
-} |
- |
-void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType) |
-{ |
- LocalFrame* frame = document().frame(); |
- if (!frame) |
- return; |
- |
- if (!frame->spellChecker().isContinuousSpellCheckingEnabled()) |
- return; |
- |
- frame->spellChecker().cancelCheck(); |
- |
- // Take a look at the selection that results after typing and determine whether we need to spellcheck. |
- // Since the word containing the current selection is never marked, this does a check to |
- // see if typing made a new word that is not in the current selection. Basically, you |
- // get this by being at the end of a word and typing a space. |
- VisiblePosition start(endingSelection().start(), endingSelection().affinity()); |
- VisiblePosition previous = start.previous(); |
- |
- VisiblePosition p1 = startOfWord(previous, LeftWordIfOnBoundary); |
- |
- if (commandType == InsertParagraphSeparator) { |
- VisiblePosition p2 = nextWordPosition(start); |
- VisibleSelection words(p1, endOfWord(p2)); |
- frame->spellChecker().markMisspellingsAfterLineBreak(words); |
- } else if (previous.isNotNull()) { |
- VisiblePosition p2 = startOfWord(start, LeftWordIfOnBoundary); |
- if (p1.deepEquivalent() != p2.deepEquivalent()) |
- frame->spellChecker().markMisspellingsAfterTypingToWord(p1, endingSelection()); |
- } |
-} |
- |
-void TypingCommand::typingAddedToOpenCommand(ETypingCommand commandTypeForAddedTyping) |
-{ |
- LocalFrame* frame = document().frame(); |
- if (!frame) |
- return; |
- |
- updatePreservesTypingStyle(commandTypeForAddedTyping); |
- updateCommandTypeOfOpenCommand(commandTypeForAddedTyping); |
- |
- // The old spellchecking code requires that checking be done first, to prevent issues like that in 6864072, where <doesn't> is marked as misspelled. |
- markMisspellingsAfterTyping(commandTypeForAddedTyping); |
- frame->editor().appliedEditing(this); |
-} |
- |
-void TypingCommand::insertText(const String &text, bool selectInsertedText) |
-{ |
- // FIXME: Need to implement selectInsertedText for cases where more than one insert is involved. |
- // This requires support from insertTextRunWithoutNewlines and insertParagraphSeparator for extending |
- // an existing selection; at the moment they can either put the caret after what's inserted or |
- // select what's inserted, but there's no way to "extend selection" to include both an old selection |
- // that ends just before where we want to insert text and the newly inserted text. |
- TypingCommandLineOperation operation(this, selectInsertedText, text); |
- forEachLineInString(text, operation); |
-} |
- |
-void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText) |
-{ |
- RefPtrWillBeRawPtr<InsertTextCommand> command = InsertTextCommand::create(document(), text, selectInsertedText, |
- m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces); |
- |
- applyCommandToComposite(command, endingSelection()); |
- |
- typingAddedToOpenCommand(InsertText); |
-} |
- |
-void TypingCommand::insertLineBreak() |
-{ |
- if (!canAppendNewLineFeedToSelection(endingSelection())) |
- return; |
- |
- applyCommandToComposite(InsertLineBreakCommand::create(document())); |
- typingAddedToOpenCommand(InsertLineBreak); |
-} |
- |
-void TypingCommand::insertParagraphSeparator() |
-{ |
- if (!canAppendNewLineFeedToSelection(endingSelection())) |
- return; |
- |
- applyCommandToComposite(InsertParagraphSeparatorCommand::create(document())); |
- typingAddedToOpenCommand(InsertParagraphSeparator); |
-} |
- |
-void TypingCommand::insertParagraphSeparatorInQuotedContent() |
-{ |
- // If the selection starts inside a table, just insert the paragraph separator normally |
- // Breaking the blockquote would also break apart the table, which is unecessary when inserting a newline |
- if (enclosingNodeOfType(endingSelection().start(), &isTableStructureNode)) { |
- insertParagraphSeparator(); |
- return; |
- } |
- |
- applyCommandToComposite(BreakBlockquoteCommand::create(document())); |
- typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent); |
-} |
- |
-bool TypingCommand::makeEditableRootEmpty() |
-{ |
- Element* root = endingSelection().rootEditableElement(); |
- if (!root || !root->hasChildren()) |
- return false; |
- |
- if (root->firstChild() == root->lastChild()) { |
- if (isHTMLBRElement(root->firstChild())) { |
- // If there is a single child and it could be a placeholder, leave it alone. |
- if (root->layoutObject() && root->layoutObject()->isLayoutBlockFlow()) |
- return false; |
- } |
- } |
- |
- while (Node* child = root->firstChild()) |
- removeNode(child); |
- |
- addBlockPlaceholderIfNeeded(root); |
- setEndingSelection(VisibleSelection(firstPositionInNode(root), DOWNSTREAM, endingSelection().isDirectional())); |
- |
- return true; |
-} |
- |
-void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool killRing) |
-{ |
- LocalFrame* frame = document().frame(); |
- if (!frame) |
- return; |
- |
- frame->spellChecker().updateMarkersForWordsAffectedByEditing(false); |
- |
- VisibleSelection selectionToDelete; |
- VisibleSelection selectionAfterUndo; |
- |
- switch (endingSelection().selectionType()) { |
- case RangeSelection: |
- selectionToDelete = endingSelection(); |
- selectionAfterUndo = selectionToDelete; |
- break; |
- case CaretSelection: { |
- // After breaking out of an empty mail blockquote, we still want continue with the deletion |
- // so actual content will get deleted, and not just the quote style. |
- if (breakOutOfEmptyMailBlockquotedParagraph()) |
- typingAddedToOpenCommand(DeleteKey); |
- |
- m_smartDelete = false; |
- |
- OwnPtrWillBeRawPtr<FrameSelection> selection = FrameSelection::create(); |
- selection->setSelection(endingSelection()); |
- selection->modify(FrameSelection::AlterationExtend, DirectionBackward, granularity); |
- if (killRing && selection->isCaret() && granularity != CharacterGranularity) |
- selection->modify(FrameSelection::AlterationExtend, DirectionBackward, CharacterGranularity); |
- |
- VisiblePosition visibleStart(endingSelection().visibleStart()); |
- if (visibleStart.previous(CannotCrossEditingBoundary).isNull()) { |
- // When the caret is at the start of the editable area in an empty list item, break out of the list item. |
- if (breakOutOfEmptyListItem()) { |
- typingAddedToOpenCommand(DeleteKey); |
- return; |
- } |
- // When there are no visible positions in the editing root, delete its entire contents. |
- if (visibleStart.next(CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty()) { |
- typingAddedToOpenCommand(DeleteKey); |
- return; |
- } |
- } |
- |
- // If we have a caret selection at the beginning of a cell, we have nothing to do. |
- Node* enclosingTableCell = enclosingNodeOfType(visibleStart.deepEquivalent(), &isTableCell); |
- if (enclosingTableCell && visibleStart.deepEquivalent() == VisiblePosition(firstPositionInNode(enclosingTableCell)).deepEquivalent()) |
- return; |
- |
- // 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(CannotCrossEditingBoundary))) { |
- // 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(FrameSelection::AlterationExtend, DirectionBackward, granularity); |
- // If the caret is just after a table, select the table and don't delete anything. |
- } else if (Element* table = isFirstPositionAfterTable(visibleStart)) { |
- setEndingSelection(VisibleSelection(positionBeforeNode(table), endingSelection().start(), DOWNSTREAM, endingSelection().isDirectional())); |
- typingAddedToOpenCommand(DeleteKey); |
- return; |
- } |
- |
- selectionToDelete = selection->selection(); |
- |
- if (granularity == CharacterGranularity && selectionToDelete.end().computeContainerNode() == selectionToDelete.start().computeContainerNode() |
- && selectionToDelete.end().computeOffsetInContainerNode() - selectionToDelete.start().computeOffsetInContainerNode() > 1) { |
- // If there are multiple Unicode code points to be deleted, adjust the range to match platform conventions. |
- selectionToDelete.setWithoutValidation(selectionToDelete.end(), selectionToDelete.end().previous(BackwardDeletion)); |
- } |
- |
- 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 VisibleSelection 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 NoSelection: |
- ASSERT_NOT_REACHED(); |
- break; |
- } |
- |
- ASSERT(!selectionToDelete.isNone()); |
- if (selectionToDelete.isNone()) |
- return; |
- |
- if (selectionToDelete.isCaret()) |
- return; |
- |
- if (killRing) |
- frame->editor().addToKillRing(selectionToDelete.toNormalizedEphemeralRange()); |
- // On Mac, 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 (frame->editor().behavior().shouldUndoOfDeleteSelectText() && m_openedByBackwardDelete) |
- setStartingSelection(selectionAfterUndo); |
- CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete); |
- setSmartDelete(false); |
- typingAddedToOpenCommand(DeleteKey); |
-} |
- |
-void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool killRing) |
-{ |
- LocalFrame* frame = document().frame(); |
- if (!frame) |
- return; |
- |
- frame->spellChecker().updateMarkersForWordsAffectedByEditing(false); |
- |
- VisibleSelection selectionToDelete; |
- VisibleSelection selectionAfterUndo; |
- |
- switch (endingSelection().selectionType()) { |
- case RangeSelection: |
- selectionToDelete = endingSelection(); |
- selectionAfterUndo = selectionToDelete; |
- break; |
- case CaretSelection: { |
- 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. |
- OwnPtrWillBeRawPtr<FrameSelection> selection = FrameSelection::create(); |
- selection->setSelection(endingSelection()); |
- selection->modify(FrameSelection::AlterationExtend, DirectionForward, granularity); |
- if (killRing && selection->isCaret() && granularity != CharacterGranularity) |
- selection->modify(FrameSelection::AlterationExtend, DirectionForward, CharacterGranularity); |
- |
- Position downstreamEnd = endingSelection().end().downstream(); |
- VisiblePosition visibleEnd = endingSelection().visibleEnd(); |
- Node* enclosingTableCell = enclosingNodeOfType(visibleEnd.deepEquivalent(), &isTableCell); |
- if (enclosingTableCell && visibleEnd.deepEquivalent() == VisiblePosition(lastPositionInNode(enclosingTableCell)).deepEquivalent()) |
- return; |
- if (visibleEnd.deepEquivalent() == endOfParagraph(visibleEnd).deepEquivalent()) |
- downstreamEnd = visibleEnd.next(CannotCrossEditingBoundary).deepEquivalent().downstream(); |
- // When deleting tables: Select the table first, then perform the deletion |
- if (isRenderedTableElement(downstreamEnd.computeContainerNode()) && downstreamEnd.computeOffsetInContainerNode() <= caretMinOffset(downstreamEnd.computeContainerNode())) { |
- setEndingSelection(VisibleSelection(endingSelection().end(), positionAfterNode(downstreamEnd.computeContainerNode()), DOWNSTREAM, endingSelection().isDirectional())); |
- typingAddedToOpenCommand(ForwardDeleteKey); |
- 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(FrameSelection::AlterationExtend, DirectionForward, 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 VisibleSelection 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.computeContainerNode() != selectionToDelete.end().computeContainerNode()) { |
- extent = selectionToDelete.extent(); |
- } else { |
- int extraCharacters; |
- if (selectionToDelete.start().computeContainerNode() == selectionToDelete.end().computeContainerNode()) |
- extraCharacters = selectionToDelete.end().computeOffsetInContainerNode() - selectionToDelete.start().computeOffsetInContainerNode(); |
- else |
- extraCharacters = selectionToDelete.end().computeOffsetInContainerNode(); |
- extent = Position(extent.computeContainerNode(), extent.computeOffsetInContainerNode() + extraCharacters); |
- } |
- selectionAfterUndo.setWithoutValidation(startingSelection().start(), extent); |
- } |
- break; |
- } |
- case NoSelection: |
- ASSERT_NOT_REACHED(); |
- break; |
- } |
- |
- ASSERT(!selectionToDelete.isNone()); |
- if (selectionToDelete.isNone()) |
- return; |
- |
- if (selectionToDelete.isCaret()) |
- return; |
- |
- if (killRing) |
- frame->editor().addToKillRing(selectionToDelete.toNormalizedEphemeralRange()); |
- // Make undo select what was deleted on Mac alone |
- if (frame->editor().behavior().shouldUndoOfDeleteSelectText()) |
- setStartingSelection(selectionAfterUndo); |
- CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete); |
- setSmartDelete(false); |
- typingAddedToOpenCommand(ForwardDeleteKey); |
-} |
- |
-void TypingCommand::deleteSelection(bool smartDelete) |
-{ |
- CompositeEditCommand::deleteSelection(smartDelete); |
- typingAddedToOpenCommand(DeleteSelection); |
-} |
- |
-void TypingCommand::updatePreservesTypingStyle(ETypingCommand commandType) |
-{ |
- switch (commandType) { |
- case DeleteSelection: |
- case DeleteKey: |
- case ForwardDeleteKey: |
- case InsertParagraphSeparator: |
- case InsertLineBreak: |
- m_preservesTypingStyle = true; |
- return; |
- case InsertParagraphSeparatorInQuotedContent: |
- case InsertText: |
- m_preservesTypingStyle = false; |
- return; |
- } |
- ASSERT_NOT_REACHED(); |
- m_preservesTypingStyle = false; |
-} |
- |
-bool TypingCommand::isTypingCommand() const |
-{ |
- return true; |
-} |
- |
-} // namespace blink |