/*
 * Copyright (C) 2005-2019 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 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 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 "TypingCommand.h"

#include "AXObjectCache.h"
#include "BreakBlockquoteCommand.h"
#include "DataTransfer.h"
#include "DeleteSelectionCommand.h"
#include "Document.h"
#include "Editing.h"
#include "Editor.h"
#include "Element.h"
#include "Frame.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
#include "InsertLineBreakCommand.h"
#include "InsertParagraphSeparatorCommand.h"
#include "InsertTextCommand.h"
#include "Logging.h"
#include "MarkupAccumulator.h"
#include "MathMLElement.h"
#include "RenderElement.h"
#include "StaticRange.h"
#include "TextIterator.h"
#include "VisibleUnits.h"

namespace WebCore {

using namespace HTMLNames;

class TypingCommandLineOperation
{
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:
    TypingCommand* m_typingCommand;
    bool m_selectInsertedText;
    const String& m_text;
};

static inline EditAction editActionForTypingCommand(TypingCommand::ETypingCommand command, TextGranularity granularity, TypingCommand::TextCompositionType compositionType, bool isAutocompletion)
{
    if (compositionType == TypingCommand::TextCompositionPending) {
        if (command == TypingCommand::InsertText)
            return EditAction::TypingInsertPendingComposition;
        if (command == TypingCommand::DeleteSelection)
            return EditAction::TypingDeletePendingComposition;
        ASSERT_NOT_REACHED();
    }

    if (compositionType == TypingCommand::TextCompositionFinal) {
        if (command == TypingCommand::InsertText)
            return EditAction::TypingInsertFinalComposition;
        if (command == TypingCommand::DeleteSelection)
            return EditAction::TypingDeleteFinalComposition;
        ASSERT_NOT_REACHED();
    }

    switch (command) {
    case TypingCommand::DeleteSelection:
        return EditAction::TypingDeleteSelection;
    case TypingCommand::DeleteKey: {
        if (granularity == WordGranularity)
            return EditAction::TypingDeleteWordBackward;
        if (granularity == LineBoundary)
            return EditAction::TypingDeleteLineBackward;
        return EditAction::TypingDeleteBackward;
    }
    case TypingCommand::ForwardDeleteKey:
        if (granularity == WordGranularity)
            return EditAction::TypingDeleteWordForward;
        if (granularity == LineBoundary)
            return EditAction::TypingDeleteLineForward;
        return EditAction::TypingDeleteForward;
    case TypingCommand::InsertText:
        return isAutocompletion ? EditAction::InsertReplacement : EditAction::TypingInsertText;
    case TypingCommand::InsertLineBreak:
        return EditAction::TypingInsertLineBreak;
    case TypingCommand::InsertParagraphSeparator:
    case TypingCommand::InsertParagraphSeparatorInQuotedContent:
        return EditAction::TypingInsertParagraph;
    default:
        return EditAction::Unspecified;
    }
}

static inline bool editActionIsDeleteByTyping(EditAction action)
{
    switch (action) {
    case EditAction::TypingDeleteSelection:
    case EditAction::TypingDeleteBackward:
    case EditAction::TypingDeleteWordBackward:
    case EditAction::TypingDeleteLineBackward:
    case EditAction::TypingDeleteForward:
    case EditAction::TypingDeleteWordForward:
    case EditAction::TypingDeleteLineForward:
        return true;
    default:
        return false;
    }
}

TypingCommand::TypingCommand(Document& document, ETypingCommand commandType, const String &textToInsert, Options options, TextGranularity granularity, TextCompositionType compositionType)
    : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity, compositionType, options & IsAutocompletion))
    , m_commandType(commandType)
    , m_textToInsert(textToInsert)
    , m_currentTextToInsert(textToInsert)
    , m_openForMoreTyping(true)
    , m_selectInsertedText(options & SelectInsertedText)
    , m_smartDelete(options & SmartDelete)
    , m_granularity(granularity)
    , m_compositionType(compositionType)
    , m_shouldAddToKillRing(options & AddsToKillRing)
    , m_isAutocompletion(options & IsAutocompletion)
    , m_openedByBackwardDelete(false)
    , m_shouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator)
    , m_shouldPreventSpellChecking(options & PreventSpellChecking)
{
    m_currentTypingEditAction = editingAction();
    updatePreservesTypingStyle(m_commandType);
}

void TypingCommand::deleteSelection(Document& document, Options options, TextCompositionType compositionType)
{
    Frame* frame = document.frame();
    ASSERT(frame);

    if (!frame->selection().isRange())
        return;

    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
        lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
        lastTypingCommand->setCompositionType(compositionType);
        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
        lastTypingCommand->deleteSelection(options & SmartDelete);
        return;
    }

    TypingCommand::create(document, DeleteSelection, emptyString(), options, compositionType)->apply();
}

void TypingCommand::deleteKeyPressed(Document& document, Options options, TextGranularity granularity)
{
    if (granularity == CharacterGranularity) {
        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document.frame());
            lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
            lastTypingCommand->setCompositionType(TextCompositionNone);
            lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
            lastTypingCommand->deleteKeyPressed(granularity, options & AddsToKillRing);
            return;
        }
    }

    TypingCommand::create(document, DeleteKey, emptyString(), 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.
    Frame* frame = document.frame();
    if (granularity == CharacterGranularity) {
        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame);
            lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
            lastTypingCommand->setCompositionType(TextCompositionNone);
            lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
            lastTypingCommand->forwardDeleteKeyPressed(granularity, options & AddsToKillRing);
            return;
        }
    }

    TypingCommand::create(document, ForwardDeleteKey, emptyString(), options, granularity)->apply();
}

void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, Frame* frame)
{
    ASSERT(frame);
    VisibleSelection currentSelection = frame->selection().selection();
    if (currentSelection == typingCommand->endingSelection())
        return;

    typingCommand->setStartingSelection(currentSelection);
    typingCommand->setEndingSelection(currentSelection);
}

void TypingCommand::insertText(Document& document, const String& text, Options options, TextCompositionType composition)
{
    Frame* frame = document.frame();
    ASSERT(frame);

    if (!text.isEmpty())
        frame->editor().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)
{
    RefPtr<Frame> frame = document.frame();
    ASSERT(frame);

    LOG(Editing, "TypingCommand::insertText (text %s)", text.utf8().data());

    VisibleSelection currentSelection = frame->selection().selection();

    String newText = dispatchBeforeTextInsertedEvent(text, selectionForInsertion, compositionType == TextCompositionPending);
    
    // 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 (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
        if (lastTypingCommand->endingSelection() != selectionForInsertion) {
            lastTypingCommand->setStartingSelection(selectionForInsertion);
            lastTypingCommand->setEndingSelection(selectionForInsertion);
        }

        lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
        lastTypingCommand->setCompositionType(compositionType);
        lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
        lastTypingCommand->insertTextAndNotifyAccessibility(newText, options & SelectInsertedText);
        return;
    }

    auto cmd = TypingCommand::create(document, InsertText, newText, options, compositionType);
    applyTextInsertionCommand(frame.get(), cmd.get(), selectionForInsertion, currentSelection);
}

void TypingCommand::insertLineBreak(Document& document, Options options)
{
    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
        lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
        lastTypingCommand->setCompositionType(TextCompositionNone);
        lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
        lastTypingCommand->insertLineBreakAndNotifyAccessibility();
        return;
    }

    TypingCommand::create(document, InsertLineBreak, emptyString(), options)->apply();
}

void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document)
{
    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
        lastTypingCommand->setIsAutocompletion(false);
        lastTypingCommand->setCompositionType(TextCompositionNone);
        lastTypingCommand->insertParagraphSeparatorInQuotedContentAndNotifyAccessibility();
        return;
    }

    TypingCommand::create(document, InsertParagraphSeparatorInQuotedContent)->apply();
}

void TypingCommand::insertParagraphSeparator(Document& document, Options options)
{
    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
        lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
        lastTypingCommand->setCompositionType(TextCompositionNone);
        lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
        lastTypingCommand->insertParagraphSeparatorAndNotifyAccessibility();
        return;
    }

    TypingCommand::create(document, InsertParagraphSeparator, emptyString(), options)->apply();
}

RefPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(Frame& frame)
{
    RefPtr<CompositeEditCommand> lastEditCommand = frame.editor().lastEditCommand();
    if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand.get())->isOpenForMoreTyping())
        return nullptr;

    return static_cast<TypingCommand*>(lastEditCommand.get());
}

bool TypingCommand::shouldDeferWillApplyCommandUntilAddingTypingCommand() const
{
    return !m_isHandlingInitialTypingCommand || editActionIsDeleteByTyping(editingAction());
}

void TypingCommand::closeTyping(Frame* frame)
{
    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame))
        lastTypingCommand->closeTyping();
}

#if PLATFORM(IOS_FAMILY)
void TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Frame* frame, const VisibleSelection& newSelection)
{
    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
        lastTypingCommand->setEndingSelection(newSelection);
        lastTypingCommand->setEndingSelectionOnLastInsertCommand(newSelection);
    }
}
#endif

void TypingCommand::postTextStateChangeNotificationForDeletion(const VisibleSelection& selection)
{
    if (!AXObjectCache::accessibilityEnabled())
        return;
    postTextStateChangeNotification(AXTextEditTypeDelete, AccessibilityObject::stringForVisiblePositionRange(selection), selection.start());
    VisiblePositionIndexRange range;
    range.startIndex.value = indexForVisiblePosition(selection.start(), range.startIndex.scope);
    range.endIndex.value = indexForVisiblePosition(selection.end(), range.endIndex.scope);
    composition()->setRangeDeletedByUnapply(range);
}

bool TypingCommand::willApplyCommand()
{
    if (shouldDeferWillApplyCommandUntilAddingTypingCommand()) {
        // The TypingCommand will handle the willApplyCommand logic separately in TypingCommand::willAddTypingToOpenCommand.
        return true;
    }

    return CompositeEditCommand::willApplyCommand();
}

void TypingCommand::doApply()
{
    if (endingSelection().isNoneOrOrphaned())
        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_shouldAddToKillRing);
        return;
    case ForwardDeleteKey:
        forwardDeleteKeyPressed(m_granularity, m_shouldAddToKillRing);
        return;
    case InsertLineBreak:
        insertLineBreakAndNotifyAccessibility();
        return;
    case InsertParagraphSeparator:
        insertParagraphSeparatorAndNotifyAccessibility();
        return;
    case InsertParagraphSeparatorInQuotedContent:
        insertParagraphSeparatorInQuotedContentAndNotifyAccessibility();
        return;
    case InsertText:
        insertTextAndNotifyAccessibility(m_textToInsert, m_selectInsertedText);
        return;
    }

    ASSERT_NOT_REACHED();
}

String TypingCommand::inputEventTypeName() const
{
    return inputTypeNameForEditingAction(m_currentTypingEditAction);
}

bool TypingCommand::isBeforeInputEventCancelable() const
{
    return m_currentTypingEditAction != EditAction::TypingInsertPendingComposition && m_currentTypingEditAction != EditAction::TypingDeletePendingComposition;
}

String TypingCommand::inputEventData() const
{
    switch (m_currentTypingEditAction) {
    case EditAction::TypingInsertText:
    case EditAction::TypingInsertPendingComposition:
    case EditAction::TypingInsertFinalComposition:
        return m_currentTextToInsert;
    case EditAction::InsertReplacement:
        return isEditingTextAreaOrTextInput() ? m_currentTextToInsert : String();
    default:
        return CompositeEditCommand::inputEventData();
    }
}

RefPtr<DataTransfer> TypingCommand::inputEventDataTransfer() const
{
    if (m_currentTypingEditAction != EditAction::InsertReplacement || isEditingTextAreaOrTextInput())
        return nullptr;

    StringBuilder htmlText;
    MarkupAccumulator::appendCharactersReplacingEntities(htmlText, m_currentTextToInsert, 0, m_currentTextToInsert.length(), EntityMaskInHTMLPCDATA);
    return DataTransfer::createForInputEvent(m_currentTextToInsert, htmlText.toString());
}

void TypingCommand::didApplyCommand()
{
    // TypingCommands handle applied editing separately (see TypingCommand::typingAddedToOpenCommand).
    m_isHandlingInitialTypingCommand = false;
}

void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType)
{
    Frame& frame = this->frame();

#if PLATFORM(MAC)
    if (!frame.editor().isContinuousSpellCheckingEnabled()
        && !frame.editor().isAutomaticQuoteSubstitutionEnabled()
        && !frame.editor().isAutomaticLinkDetectionEnabled()
        && !frame.editor().isAutomaticDashSubstitutionEnabled()
        && !frame.editor().isAutomaticTextReplacementEnabled())
            return;
    if (frame.editor().isHandlingAcceptedCandidate())
        return;
#else
    if (!frame.editor().isContinuousSpellCheckingEnabled())
        return;
#endif
    // 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();
    if (previous.isNotNull()) {
#if !PLATFORM(IOS_FAMILY)
        VisiblePosition p1 = startOfWord(previous, LeftWordIfOnBoundary);
        VisiblePosition p2 = startOfWord(start, LeftWordIfOnBoundary);
        if (p1 != p2) {
            RefPtr<Range> range = makeRange(p1, p2);
            String strippedPreviousWord;
            if (range && (commandType == TypingCommand::InsertText || commandType == TypingCommand::InsertLineBreak || commandType == TypingCommand::InsertParagraphSeparator || commandType == TypingCommand::InsertParagraphSeparatorInQuotedContent))
                strippedPreviousWord = plainText(range.get()).stripWhiteSpace();
            frame.editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), !strippedPreviousWord.isEmpty());
        } else if (commandType == TypingCommand::InsertText)
            frame.editor().startAlternativeTextUITimer();
#else
        UNUSED_PARAM(commandType);
        // If this bug gets fixed, this PLATFORM(IOS_FAMILY) code could be removed:
        // <rdar://problem/7259611> Word boundary code on iPhone gives different results than desktop
        EWordSide startWordSide = LeftWordIfOnBoundary;
        UChar32 c = previous.characterAfter();
        // FIXME: VisiblePosition::characterAfter() and characterBefore() do not emit newlines the same
        // way as TextIterator, so we do an isEndOfParagraph check here.
        if (isSpaceOrNewline(c) || c == noBreakSpace || isEndOfParagraph(previous)) {
            startWordSide = RightWordIfOnBoundary;
        }
        VisiblePosition p1 = startOfWord(previous, startWordSide);
        VisiblePosition p2 = startOfWord(start, startWordSide);
        if (p1 != p2)
            frame.editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), false);
#endif // !PLATFORM(IOS_FAMILY)
    }
}

bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity, const String& text, RefPtr<Range>&& range)
{
    m_currentTextToInsert = text;
    m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity, m_compositionType, m_isAutocompletion);

    if (!shouldDeferWillApplyCommandUntilAddingTypingCommand())
        return true;

    if (!range || isEditingTextAreaOrTextInput())
        return frame().editor().willApplyEditing(*this, CompositeEditCommand::targetRangesForBindings());

    return frame().editor().willApplyEditing(*this, { 1, StaticRange::createFromRange(*range) });
}

void TypingCommand::typingAddedToOpenCommand(ETypingCommand commandTypeForAddedTyping)
{
    Frame& frame = this->frame();

    updatePreservesTypingStyle(commandTypeForAddedTyping);

#if PLATFORM(COCOA)
    frame.editor().appliedEditing(*this);
    // Since the spellchecking code may also perform corrections and other replacements, it should happen after the typing changes.
    if (!m_shouldPreventSpellChecking)
        markMisspellingsAfterTyping(commandTypeForAddedTyping);
#else
    // 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);
#endif
}

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::insertTextAndNotifyAccessibility(const String &text, bool selectInsertedText)
{
    LOG(Editing, "TypingCommand %p insertTextAndNotifyAccessibility (text %s, selectInsertedText %d)", this, text.utf8().data(), selectInsertedText);

    AccessibilityReplacedText replacedText(frame().selection().selection());
    insertText(text, selectInsertedText);
    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, text, frame().selection().selection());
    composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
}

void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText)
{
    if (!willAddTypingToOpenCommand(InsertText, CharacterGranularity, text))
        return;

    auto command = InsertTextCommand::create(document(), text, selectInsertedText,
        m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces, EditAction::TypingInsertText);

    applyCommandToComposite(WTFMove(command), endingSelection());

    Frame& frame = this->frame();
    Ref<Frame> protector(frame);
    typingAddedToOpenCommand(InsertText);
}

void TypingCommand::insertLineBreak()
{
    if (!canAppendNewLineFeedToSelection(endingSelection()))
        return;

    if (!willAddTypingToOpenCommand(InsertLineBreak, LineGranularity))
        return;

    applyCommandToComposite(InsertLineBreakCommand::create(document()));

    Frame& frame = this->frame();
    Ref<Frame> protector(frame);
    typingAddedToOpenCommand(InsertLineBreak);
}

void TypingCommand::insertLineBreakAndNotifyAccessibility()
{
    AccessibilityReplacedText replacedText(frame().selection().selection());
    insertLineBreak();
    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
    composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
}

void TypingCommand::insertParagraphSeparator()
{
    if (!canAppendNewLineFeedToSelection(endingSelection()))
        return;

    if (!willAddTypingToOpenCommand(InsertParagraphSeparator, ParagraphGranularity))
        return;

    applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), false, false, EditAction::TypingInsertParagraph));

    Frame& frame = this->frame();
    Ref<Frame> protector(frame);
    typingAddedToOpenCommand(InsertParagraphSeparator);
}

void TypingCommand::insertParagraphSeparatorAndNotifyAccessibility()
{
    AccessibilityReplacedText replacedText(frame().selection().selection());
    insertParagraphSeparator();
    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
    composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
}

void TypingCommand::insertParagraphSeparatorInQuotedContent()
{
    if (!willAddTypingToOpenCommand(InsertParagraphSeparatorInQuotedContent, ParagraphGranularity))
        return;

    // 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()));

    Frame& frame = this->frame();
    Ref<Frame> protector(frame);
    typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent);
}

void TypingCommand::insertParagraphSeparatorInQuotedContentAndNotifyAccessibility()
{
    AccessibilityReplacedText replacedText(frame().selection().selection());
    insertParagraphSeparatorInQuotedContent();
    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
    composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
}

bool TypingCommand::makeEditableRootEmpty()
{
    Element* root = endingSelection().rootEditableElement();
    if (!root || !root->firstChild())
        return false;

    if (root->firstChild() == root->lastChild() && root->firstElementChild() && root->firstElementChild()->hasTagName(brTag)) {
        // If there is a single child and it could be a placeholder, leave it alone.
        if (root->renderer() && root->renderer()->isRenderBlockFlow())
            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 shouldAddToKillRing)
{
    Frame& frame = this->frame();
    Ref<Frame> protector(frame);

    frame.editor().updateMarkersForWordsAffectedByEditing(false);

    VisibleSelection selectionToDelete;
    VisibleSelection selectionAfterUndo;
    bool expandForSpecialElements = !endingSelection().isCaret();

    switch (endingSelection().selectionType()) {
    case VisibleSelection::RangeSelection:
        selectionToDelete = endingSelection();
        selectionAfterUndo = selectionToDelete;
        break;
    case VisibleSelection::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;

        FrameSelection selection;
        selection.setSelection(endingSelection());
        selection.modify(FrameSelection::AlterationExtend, DirectionBackward, granularity);
        if (shouldAddToKillRing && selection.isCaret() && granularity != CharacterGranularity)
            selection.modify(FrameSelection::AlterationExtend, DirectionBackward, CharacterGranularity);

        const VisiblePosition& visibleStart = endingSelection().visibleStart();
        const VisiblePosition& previousPosition = visibleStart.previous(CannotCrossEditingBoundary);
        Node* enclosingTableCell = enclosingNodeOfType(visibleStart.deepEquivalent(), &isTableCell);
        const Node* enclosingTableCellForPreviousPosition = enclosingNodeOfType(previousPosition.deepEquivalent(), &isTableCell);
        if (previousPosition.isNull() || enclosingTableCell != enclosingTableCellForPreviousPosition) {
            // When the caret is at the start of the editable area in an empty list item, break out of the list item.
            if (auto deleteListSelection = shouldBreakOutOfEmptyListItem()) {
                if (willAddTypingToOpenCommand(DeleteKey, granularity, { }, Range::create(document(), deleteListSelection.value().start(), deleteListSelection.value().end()))) {
                    breakOutOfEmptyListItem();
                    typingAddedToOpenCommand(DeleteKey);
                }
                return;
            }
        }
        if (previousPosition.isNull()) {
            // When there are no visible positions in the editing root, delete its entire contents.
            // FIXME: Dispatch a `beforeinput` event here and bail if preventDefault() was invoked.
            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.
        if (enclosingTableCell && visibleStart == firstPositionInNode(enclosingTableCell))
            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 (Node* table = isFirstPositionAfterTable(visibleStart)) {
            setEndingSelection(VisibleSelection(positionBeforeNode(table), endingSelection().start(), DOWNSTREAM, endingSelection().isDirectional()));
            typingAddedToOpenCommand(DeleteKey);
            return;
        }

        selectionToDelete = selection.selection();

        if (granularity == CharacterGranularity && selectionToDelete.end().containerNode() == selectionToDelete.start().containerNode()
            && 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 VisibleSelection::NoSelection:
        ASSERT_NOT_REACHED();
        break;
    }
    
    ASSERT(!selectionToDelete.isNone());
    if (selectionToDelete.isNone()) {
#if PLATFORM(IOS_FAMILY)
        // Workaround for this bug:
        // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text
        setEndingSelection(frame.selection().selection());
        closeTyping(&frame);
#endif
        return;
    }
    
    if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
        return;
    
    if (!willAddTypingToOpenCommand(DeleteKey, granularity, { }, selectionToDelete.firstRange()))
        return;

    if (shouldAddToKillRing)
        frame.editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange().get(), Editor::KillRingInsertionMode::PrependText);

    // Post the accessibility notification before actually deleting the content while selectionToDelete is still valid
    postTextStateChangeNotificationForDeletion(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, /* mergeBlocksAfterDelete*/ true, /* replace*/ false, expandForSpecialElements, /*sanitizeMarkup*/ true);
    setSmartDelete(false);
    typingAddedToOpenCommand(DeleteKey);
}

void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing)
{
    Frame& frame = this->frame();
    Ref<Frame> protector(frame);

    frame.editor().updateMarkersForWordsAffectedByEditing(false);

    VisibleSelection selectionToDelete;
    VisibleSelection selectionAfterUndo;
    bool expandForSpecialElements = !endingSelection().isCaret();

    switch (endingSelection().selectionType()) {
    case VisibleSelection::RangeSelection:
        selectionToDelete = endingSelection();
        selectionAfterUndo = selectionToDelete;
        break;
    case VisibleSelection::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.
        FrameSelection selection;
        selection.setSelection(endingSelection());
        selection.modify(FrameSelection::AlterationExtend, DirectionForward, granularity);
        if (shouldAddToKillRing && 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 == lastPositionInNode(enclosingTableCell))
            return;
        if (visibleEnd == endOfParagraph(visibleEnd))
            downstreamEnd = visibleEnd.next(CannotCrossEditingBoundary).deepEquivalent().downstream();
        // When deleting tables: Select the table first, then perform the deletion
        if (downstreamEnd.containerNode() && downstreamEnd.containerNode()->renderer() && downstreamEnd.containerNode()->renderer()->isTable()
            && downstreamEnd.computeOffsetInContainerNode() <= caretMinOffset(*downstreamEnd.containerNode())) {
            setEndingSelection(VisibleSelection(endingSelection().end(), positionAfterNode(downstreamEnd.containerNode()), 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.containerNode() != selectionToDelete.end().containerNode())
                extent = selectionToDelete.extent();
            else {
                int extraCharacters;
                if (selectionToDelete.start().containerNode() == selectionToDelete.end().containerNode())
                    extraCharacters = selectionToDelete.end().computeOffsetInContainerNode() - selectionToDelete.start().computeOffsetInContainerNode();
                else
                    extraCharacters = selectionToDelete.end().computeOffsetInContainerNode();
                extent = Position(extent.containerNode(), extent.computeOffsetInContainerNode() + extraCharacters, Position::PositionIsOffsetInAnchor);
            }
            selectionAfterUndo.setWithoutValidation(startingSelection().start(), extent);
        }
        break;
    }
    case VisibleSelection::NoSelection:
        ASSERT_NOT_REACHED();
        break;
    }
    
    ASSERT(!selectionToDelete.isNone());
    if (selectionToDelete.isNone()) {
#if PLATFORM(IOS_FAMILY)
        // Workaround for this bug:
        // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text
        setEndingSelection(frame.selection().selection());
        closeTyping(&frame);
#endif
        return;
    }
    
    if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
        return;

    if (!willAddTypingToOpenCommand(ForwardDeleteKey, granularity, { }, selectionToDelete.firstRange()))
        return;

    // Post the accessibility notification before actually deleting the content while selectionToDelete is still valid
    postTextStateChangeNotificationForDeletion(selectionToDelete);

    if (shouldAddToKillRing)
        frame.editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange().get(), Editor::KillRingInsertionMode::AppendText);
    // make undo select what was deleted
    setStartingSelection(selectionAfterUndo);
    CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete, /* mergeBlocksAfterDelete*/ true, /* replace*/ false, expandForSpecialElements, /*sanitizeMarkup*/ true);
    setSmartDelete(false);
    typingAddedToOpenCommand(ForwardDeleteKey);
}

void TypingCommand::deleteSelection(bool smartDelete)
{
    if (!willAddTypingToOpenCommand(DeleteSelection, CharacterGranularity))
        return;

    CompositeEditCommand::deleteSelection(smartDelete);
    typingAddedToOpenCommand(DeleteSelection);
}

#if PLATFORM(IOS_FAMILY)
class FriendlyEditCommand : public EditCommand {
public:
    void setEndingSelection(const VisibleSelection& selection)
    {
        EditCommand::setEndingSelection(selection);
    }
};

void TypingCommand::setEndingSelectionOnLastInsertCommand(const VisibleSelection& selection)
{
    if (!m_commands.isEmpty()) {
        EditCommand* lastCommand = m_commands.last().get();
        if (lastCommand->isInsertTextCommand())
            static_cast<FriendlyEditCommand*>(lastCommand)->setEndingSelection(selection);
    }
}
#endif

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 WebCore
