mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 1 | /* |
bfulgham@apple.com | 1f2e42b | 2019-05-28 21:02:38 +0000 | [diff] [blame] | 2 | * Copyright (C) 2005-2019 Apple Inc. All rights reserved. |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * 1. Redistributions of source code must retain the above copyright |
| 8 | * notice, this list of conditions and the following disclaimer. |
| 9 | * 2. Redistributions in binary form must reproduce the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer in the |
| 11 | * documentation and/or other materials provided with the distribution. |
| 12 | * |
mjs@apple.com | 9204733 | 2014-03-15 04:08:27 +0000 | [diff] [blame] | 13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
mjs@apple.com | 9204733 | 2014-03-15 04:08:27 +0000 | [diff] [blame] | 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 | */ |
| 25 | |
mjs | b64c50a | 2005-10-03 21:13:12 +0000 | [diff] [blame] | 26 | #include "config.h" |
darin | a68e043 | 2006-02-14 21:40:54 +0000 | [diff] [blame] | 27 | #include "TypingCommand.h" |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 28 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 29 | #include "AXObjectCache.h" |
darin | a68e043 | 2006-02-14 21:40:54 +0000 | [diff] [blame] | 30 | #include "BreakBlockquoteCommand.h" |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 31 | #include "DataTransfer.h" |
lweintraub | 6d37780 | 2006-07-07 19:33:28 +0000 | [diff] [blame] | 32 | #include "DeleteSelectionCommand.h" |
jer.noble@apple.com | 117db59 | 2021-10-13 05:54:46 +0000 | [diff] [blame] | 33 | #include "DocumentInlines.h" |
commit-queue@webkit.org | 02ea7a2 | 2017-03-03 06:35:25 +0000 | [diff] [blame] | 34 | #include "Editing.h" |
ggaren | 57aa2fe | 2006-10-31 01:01:01 +0000 | [diff] [blame] | 35 | #include "Editor.h" |
eseidel | 40eb1b9 | 2006-03-25 22:20:36 +0000 | [diff] [blame] | 36 | #include "Element.h" |
darin | a68e043 | 2006-02-14 21:40:54 +0000 | [diff] [blame] | 37 | #include "Frame.h" |
darin@apple.com | 15708b1 | 2014-03-16 16:38:58 +0000 | [diff] [blame] | 38 | #include "HTMLElement.h" |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 39 | #include "HTMLNames.h" |
darin | a68e043 | 2006-02-14 21:40:54 +0000 | [diff] [blame] | 40 | #include "InsertLineBreakCommand.h" |
| 41 | #include "InsertParagraphSeparatorCommand.h" |
| 42 | #include "InsertTextCommand.h" |
simon.fraser@apple.com | 906b086 | 2016-08-28 00:36:05 +0000 | [diff] [blame] | 43 | #include "Logging.h" |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 44 | #include "MarkupAccumulator.h" |
darin@apple.com | 15708b1 | 2014-03-16 16:38:58 +0000 | [diff] [blame] | 45 | #include "MathMLElement.h" |
aperez@igalia.com | fa121a6 | 2020-08-03 16:42:33 +0000 | [diff] [blame] | 46 | #include "Range.h" |
antti@apple.com | c3cbb6b | 2013-09-20 08:59:25 +0000 | [diff] [blame] | 47 | #include "RenderElement.h" |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 48 | #include "StaticRange.h" |
darin@apple.com | 51e2d46 | 2014-03-03 02:30:37 +0000 | [diff] [blame] | 49 | #include "TextIterator.h" |
tkent@chromium.org | 8c35c12 | 2013-03-06 13:00:14 +0000 | [diff] [blame] | 50 | #include "VisibleUnits.h" |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 51 | |
darin | a68e043 | 2006-02-14 21:40:54 +0000 | [diff] [blame] | 52 | namespace WebCore { |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 53 | |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 54 | using namespace HTMLNames; |
| 55 | |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 56 | class TypingCommandLineOperation |
commit-queue@webkit.org | b887b8c | 2011-03-17 06:31:00 +0000 | [diff] [blame] | 57 | { |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 58 | public: |
| 59 | TypingCommandLineOperation(TypingCommand* typingCommand, bool selectInsertedText, const String& text) |
| 60 | : m_typingCommand(typingCommand) |
| 61 | , m_selectInsertedText(selectInsertedText) |
| 62 | , m_text(text) |
| 63 | { } |
| 64 | |
| 65 | void operator()(size_t lineOffset, size_t lineLength, bool isLastLine) const |
| 66 | { |
| 67 | if (isLastLine) { |
| 68 | if (!lineOffset || lineLength > 0) |
| 69 | m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), m_selectInsertedText); |
| 70 | } else { |
| 71 | if (lineLength > 0) |
| 72 | m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), false); |
| 73 | m_typingCommand->insertParagraphSeparator(); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | private: |
| 78 | TypingCommand* m_typingCommand; |
| 79 | bool m_selectInsertedText; |
| 80 | const String& m_text; |
| 81 | }; |
commit-queue@webkit.org | b887b8c | 2011-03-17 06:31:00 +0000 | [diff] [blame] | 82 | |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 83 | static inline EditAction editActionForTypingCommand(TypingCommand::ETypingCommand command, TextGranularity granularity, TypingCommand::TextCompositionType compositionType, bool isAutocompletion) |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 84 | { |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 85 | if (compositionType == TypingCommand::TextCompositionPending) { |
| 86 | if (command == TypingCommand::InsertText) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 87 | return EditAction::TypingInsertPendingComposition; |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 88 | if (command == TypingCommand::DeleteSelection) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 89 | return EditAction::TypingDeletePendingComposition; |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 90 | ASSERT_NOT_REACHED(); |
| 91 | } |
| 92 | |
| 93 | if (compositionType == TypingCommand::TextCompositionFinal) { |
| 94 | if (command == TypingCommand::InsertText) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 95 | return EditAction::TypingInsertFinalComposition; |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 96 | if (command == TypingCommand::DeleteSelection) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 97 | return EditAction::TypingDeleteFinalComposition; |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 98 | ASSERT_NOT_REACHED(); |
| 99 | } |
| 100 | |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 101 | switch (command) { |
| 102 | case TypingCommand::DeleteSelection: |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 103 | return EditAction::TypingDeleteSelection; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 104 | case TypingCommand::DeleteKey: { |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 105 | if (granularity == TextGranularity::WordGranularity) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 106 | return EditAction::TypingDeleteWordBackward; |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 107 | if (granularity == TextGranularity::LineBoundary) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 108 | return EditAction::TypingDeleteLineBackward; |
| 109 | return EditAction::TypingDeleteBackward; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 110 | } |
| 111 | case TypingCommand::ForwardDeleteKey: |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 112 | if (granularity == TextGranularity::WordGranularity) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 113 | return EditAction::TypingDeleteWordForward; |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 114 | if (granularity == TextGranularity::LineBoundary) |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 115 | return EditAction::TypingDeleteLineForward; |
| 116 | return EditAction::TypingDeleteForward; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 117 | case TypingCommand::InsertText: |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 118 | return isAutocompletion ? EditAction::InsertReplacement : EditAction::TypingInsertText; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 119 | case TypingCommand::InsertLineBreak: |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 120 | return EditAction::TypingInsertLineBreak; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 121 | case TypingCommand::InsertParagraphSeparator: |
| 122 | case TypingCommand::InsertParagraphSeparatorInQuotedContent: |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 123 | return EditAction::TypingInsertParagraph; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 124 | default: |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 125 | return EditAction::Unspecified; |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 126 | } |
| 127 | } |
| 128 | |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 129 | static inline bool editActionIsDeleteByTyping(EditAction action) |
| 130 | { |
| 131 | switch (action) { |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 132 | case EditAction::TypingDeleteSelection: |
| 133 | case EditAction::TypingDeleteBackward: |
| 134 | case EditAction::TypingDeleteWordBackward: |
| 135 | case EditAction::TypingDeleteLineBackward: |
| 136 | case EditAction::TypingDeleteForward: |
| 137 | case EditAction::TypingDeleteWordForward: |
| 138 | case EditAction::TypingDeleteLineForward: |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 139 | return true; |
| 140 | default: |
| 141 | return false; |
| 142 | } |
| 143 | } |
| 144 | |
akling@apple.com | d455eb6 | 2013-09-01 05:30:31 +0000 | [diff] [blame] | 145 | TypingCommand::TypingCommand(Document& document, ETypingCommand commandType, const String &textToInsert, Options options, TextGranularity granularity, TextCompositionType compositionType) |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 146 | : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity, compositionType, options & IsAutocompletion)) |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 147 | , m_commandType(commandType) |
| 148 | , m_textToInsert(textToInsert) |
wenson_hsieh@apple.com | 3747aa5 | 2016-10-10 18:30:03 +0000 | [diff] [blame] | 149 | , m_currentTextToInsert(textToInsert) |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 150 | , m_openForMoreTyping(true) |
| 151 | , m_selectInsertedText(options & SelectInsertedText) |
commit-queue@webkit.org | 6aedb68 | 2011-04-08 03:59:34 +0000 | [diff] [blame] | 152 | , m_smartDelete(options & SmartDelete) |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 153 | , m_granularity(granularity) |
| 154 | , m_compositionType(compositionType) |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 155 | , m_shouldAddToKillRing(options & AddsToKillRing) |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 156 | , m_isAutocompletion(options & IsAutocompletion) |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 157 | , m_openedByBackwardDelete(false) |
| 158 | , m_shouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator) |
commit-queue@webkit.org | 6aedb68 | 2011-04-08 03:59:34 +0000 | [diff] [blame] | 159 | , m_shouldPreventSpellChecking(options & PreventSpellChecking) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 160 | { |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 161 | m_currentTypingEditAction = editingAction(); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 162 | updatePreservesTypingStyle(m_commandType); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 163 | } |
| 164 | |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 165 | void TypingCommand::deleteSelection(Document& document, Options options, TextCompositionType compositionType) |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 166 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 167 | if (!document.selection().isRange()) |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 168 | return; |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 169 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 170 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 171 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 172 | lastTypingCommand->setCompositionType(compositionType); |
commit-queue@webkit.org | 6aedb68 | 2011-04-08 03:59:34 +0000 | [diff] [blame] | 173 | lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
| 174 | lastTypingCommand->deleteSelection(options & SmartDelete); |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 175 | return; |
| 176 | } |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 177 | |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 178 | TypingCommand::create(document, DeleteSelection, emptyString(), options, compositionType)->apply(); |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 179 | } |
| 180 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 181 | void TypingCommand::deleteKeyPressed(Document& document, Options options, TextGranularity granularity) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 182 | { |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 183 | if (granularity == TextGranularity::CharacterGranularity) { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 184 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
| 185 | updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document); |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 186 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 187 | lastTypingCommand->setCompositionType(TextCompositionNone); |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 188 | lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 189 | lastTypingCommand->deleteKeyPressed(granularity, options & AddsToKillRing); |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 190 | return; |
| 191 | } |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 192 | } |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 193 | |
cdumez@apple.com | 327d6c6 | 2016-07-16 04:51:45 +0000 | [diff] [blame] | 194 | TypingCommand::create(document, DeleteKey, emptyString(), options, granularity)->apply(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 195 | } |
| 196 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 197 | void TypingCommand::forwardDeleteKeyPressed(Document& document, Options options, TextGranularity granularity) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 198 | { |
justing | 4a536cf | 2007-08-17 00:29:36 +0000 | [diff] [blame] | 199 | // FIXME: Forward delete in TextEdit appears to open and close a new typing command. |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 200 | if (granularity == TextGranularity::CharacterGranularity) { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 201 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
| 202 | updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document); |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 203 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 204 | lastTypingCommand->setCompositionType(TextCompositionNone); |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 205 | lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 206 | lastTypingCommand->forwardDeleteKeyPressed(granularity, options & AddsToKillRing); |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 207 | return; |
| 208 | } |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 209 | } |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 210 | |
cdumez@apple.com | 327d6c6 | 2016-07-16 04:51:45 +0000 | [diff] [blame] | 211 | TypingCommand::create(document, ForwardDeleteKey, emptyString(), options, granularity)->apply(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 212 | } |
| 213 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 214 | void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, Document& document) |
rniwa@webkit.org | 54a246d | 2010-12-03 19:26:22 +0000 | [diff] [blame] | 215 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 216 | VisibleSelection currentSelection = document.selection().selection(); |
rniwa@webkit.org | 54a246d | 2010-12-03 19:26:22 +0000 | [diff] [blame] | 217 | if (currentSelection == typingCommand->endingSelection()) |
| 218 | return; |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 219 | |
rniwa@webkit.org | 54a246d | 2010-12-03 19:26:22 +0000 | [diff] [blame] | 220 | typingCommand->setStartingSelection(currentSelection); |
| 221 | typingCommand->setEndingSelection(currentSelection); |
| 222 | } |
rniwa@webkit.org | 54a246d | 2010-12-03 19:26:22 +0000 | [diff] [blame] | 223 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 224 | void TypingCommand::insertText(Document& document, const String& text, Options options, TextCompositionType composition) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 225 | { |
commit-queue@webkit.org | 08abac6 | 2010-10-28 23:45:26 +0000 | [diff] [blame] | 226 | if (!text.isEmpty()) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 227 | document.editor().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0])); |
morrita@google.com | 4e40c8b | 2011-04-08 21:21:44 +0000 | [diff] [blame] | 228 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 229 | insertText(document, text, document.selection().selection(), options, composition); |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 230 | } |
| 231 | |
rniwa@webkit.org | 78bbc94 | 2011-05-05 18:14:43 +0000 | [diff] [blame] | 232 | // FIXME: We shouldn't need to take selectionForInsertion. It should be identical to FrameSelection's current selection. |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 233 | void TypingCommand::insertText(Document& document, const String& text, const VisibleSelection& selectionForInsertion, Options options, TextCompositionType compositionType) |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 234 | { |
simon.fraser@apple.com | 906b086 | 2016-08-28 00:36:05 +0000 | [diff] [blame] | 235 | LOG(Editing, "TypingCommand::insertText (text %s)", text.utf8().data()); |
| 236 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 237 | VisibleSelection currentSelection = document.selection().selection(); |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 238 | |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 239 | String newText = dispatchBeforeTextInsertedEvent(text, selectionForInsertion, compositionType == TextCompositionPending); |
adele | 1abf959 | 2006-03-06 05:52:31 +0000 | [diff] [blame] | 240 | |
adele | 6ef54cf7 | 2007-01-31 22:55:56 +0000 | [diff] [blame] | 241 | // Set the starting and ending selection appropriately if we are using a selection |
| 242 | // that is different from the current selection. In the future, we should change EditCommand |
| 243 | // to deal with custom selections in a general way that can be used by all of the commands. |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 244 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
rniwa@webkit.org | 54a246d | 2010-12-03 19:26:22 +0000 | [diff] [blame] | 245 | if (lastTypingCommand->endingSelection() != selectionForInsertion) { |
adele | 6ef54cf7 | 2007-01-31 22:55:56 +0000 | [diff] [blame] | 246 | lastTypingCommand->setStartingSelection(selectionForInsertion); |
| 247 | lastTypingCommand->setEndingSelection(selectionForInsertion); |
darin | d4408fc | 2007-04-24 17:37:50 +0000 | [diff] [blame] | 248 | } |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 249 | |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 250 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
morrita@google.com | 6a3e425 | 2011-01-24 06:53:34 +0000 | [diff] [blame] | 251 | lastTypingCommand->setCompositionType(compositionType); |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 252 | lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
commit-queue@webkit.org | 6aedb68 | 2011-04-08 03:59:34 +0000 | [diff] [blame] | 253 | lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 254 | lastTypingCommand->insertTextAndNotifyAccessibility(newText, options & SelectInsertedText); |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 255 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 256 | } |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 257 | |
yusukesuzuki@slowstart.org | ae5a8bd | 2018-12-22 06:37:39 +0000 | [diff] [blame] | 258 | auto cmd = TypingCommand::create(document, InsertText, newText, options, compositionType); |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 259 | applyTextInsertionCommand(document.frame(), cmd.get(), selectionForInsertion, currentSelection); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 260 | } |
| 261 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 262 | void TypingCommand::insertLineBreak(Document& document, Options options) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 263 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 264 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 265 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 266 | lastTypingCommand->setCompositionType(TextCompositionNone); |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 267 | lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 268 | lastTypingCommand->insertLineBreakAndNotifyAccessibility(); |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 269 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 270 | } |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 271 | |
cdumez@apple.com | 2fecce7 | 2017-05-05 05:09:56 +0000 | [diff] [blame] | 272 | TypingCommand::create(document, InsertLineBreak, emptyString(), options)->apply(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 273 | } |
| 274 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 275 | void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 276 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 277 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 278 | lastTypingCommand->setIsAutocompletion(false); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 279 | lastTypingCommand->setCompositionType(TextCompositionNone); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 280 | lastTypingCommand->insertParagraphSeparatorInQuotedContentAndNotifyAccessibility(); |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 281 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 282 | } |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 283 | |
cdumez@apple.com | 2fecce7 | 2017-05-05 05:09:56 +0000 | [diff] [blame] | 284 | TypingCommand::create(document, InsertParagraphSeparatorInQuotedContent)->apply(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 285 | } |
| 286 | |
akling@apple.com | 62b19a8 | 2013-10-05 03:34:51 +0000 | [diff] [blame] | 287 | void TypingCommand::insertParagraphSeparator(Document& document, Options options) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 288 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 289 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 290 | lastTypingCommand->setIsAutocompletion(options & IsAutocompletion); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 291 | lastTypingCommand->setCompositionType(TextCompositionNone); |
commit-queue@webkit.org | 5396fd9 | 2011-03-01 20:31:40 +0000 | [diff] [blame] | 292 | lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 293 | lastTypingCommand->insertParagraphSeparatorAndNotifyAccessibility(); |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 294 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 295 | } |
harrison | 78e6583 | 2006-02-14 03:29:43 +0000 | [diff] [blame] | 296 | |
cdumez@apple.com | 2fecce7 | 2017-05-05 05:09:56 +0000 | [diff] [blame] | 297 | TypingCommand::create(document, InsertParagraphSeparator, emptyString(), options)->apply(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 298 | } |
| 299 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 300 | RefPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(Document& document) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 301 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 302 | RefPtr<CompositeEditCommand> lastEditCommand = document.editor().lastEditCommand(); |
rniwa@webkit.org | 6c2ef9d | 2012-01-19 21:41:08 +0000 | [diff] [blame] | 303 | if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand.get())->isOpenForMoreTyping()) |
gyuyoung.kim@webkit.org | 842c786 | 2016-03-23 14:05:54 +0000 | [diff] [blame] | 304 | return nullptr; |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 305 | |
rniwa@webkit.org | 6c2ef9d | 2012-01-19 21:41:08 +0000 | [diff] [blame] | 306 | return static_cast<TypingCommand*>(lastEditCommand.get()); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 307 | } |
| 308 | |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 309 | bool TypingCommand::shouldDeferWillApplyCommandUntilAddingTypingCommand() const |
| 310 | { |
| 311 | return !m_isHandlingInitialTypingCommand || editActionIsDeleteByTyping(editingAction()); |
| 312 | } |
| 313 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 314 | void TypingCommand::closeTyping(Document& document) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 315 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 316 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) |
rniwa@webkit.org | 166a086c | 2011-12-07 09:03:51 +0000 | [diff] [blame] | 317 | lastTypingCommand->closeTyping(); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 318 | } |
| 319 | |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 320 | #if PLATFORM(IOS_FAMILY) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 321 | void TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Document& document, const VisibleSelection& newSelection) |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 322 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 323 | if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) { |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 324 | lastTypingCommand->setEndingSelection(newSelection); |
| 325 | lastTypingCommand->setEndingSelectionOnLastInsertCommand(newSelection); |
| 326 | } |
| 327 | } |
| 328 | #endif |
| 329 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 330 | void TypingCommand::postTextStateChangeNotificationForDeletion(const VisibleSelection& selection) |
| 331 | { |
| 332 | if (!AXObjectCache::accessibilityEnabled()) |
| 333 | return; |
| 334 | postTextStateChangeNotification(AXTextEditTypeDelete, AccessibilityObject::stringForVisiblePositionRange(selection), selection.start()); |
| 335 | VisiblePositionIndexRange range; |
darin@apple.com | 2e2bfd7 | 2020-07-29 16:36:40 +0000 | [diff] [blame] | 336 | range.startIndex.value = indexForVisiblePosition(selection.visibleStart(), range.startIndex.scope); |
| 337 | range.endIndex.value = indexForVisiblePosition(selection.visibleEnd(), range.endIndex.scope); |
d_russell@apple.com | d60eb24 | 2016-05-13 19:34:48 +0000 | [diff] [blame] | 338 | composition()->setRangeDeletedByUnapply(range); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 339 | } |
| 340 | |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 341 | bool TypingCommand::willApplyCommand() |
| 342 | { |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 343 | if (shouldDeferWillApplyCommandUntilAddingTypingCommand()) { |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 344 | // The TypingCommand will handle the willApplyCommand logic separately in TypingCommand::willAddTypingToOpenCommand. |
| 345 | return true; |
| 346 | } |
| 347 | |
| 348 | return CompositeEditCommand::willApplyCommand(); |
| 349 | } |
| 350 | |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 351 | void TypingCommand::doApply() |
| 352 | { |
rniwa@webkit.org | 0a8ef82 | 2016-06-08 19:19:22 +0000 | [diff] [blame] | 353 | if (endingSelection().isNoneOrOrphaned()) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 354 | return; |
rniwa@webkit.org | 0a8ef82 | 2016-06-08 19:19:22 +0000 | [diff] [blame] | 355 | |
justing | 4a536cf | 2007-08-17 00:29:36 +0000 | [diff] [blame] | 356 | if (m_commandType == DeleteKey) |
| 357 | if (m_commands.isEmpty()) |
| 358 | m_openedByBackwardDelete = true; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 359 | |
| 360 | switch (m_commandType) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 361 | case DeleteSelection: |
| 362 | deleteSelection(m_smartDelete); |
| 363 | return; |
| 364 | case DeleteKey: |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 365 | deleteKeyPressed(m_granularity, m_shouldAddToKillRing); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 366 | return; |
| 367 | case ForwardDeleteKey: |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 368 | forwardDeleteKeyPressed(m_granularity, m_shouldAddToKillRing); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 369 | return; |
| 370 | case InsertLineBreak: |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 371 | insertLineBreakAndNotifyAccessibility(); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 372 | return; |
| 373 | case InsertParagraphSeparator: |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 374 | insertParagraphSeparatorAndNotifyAccessibility(); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 375 | return; |
| 376 | case InsertParagraphSeparatorInQuotedContent: |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 377 | insertParagraphSeparatorInQuotedContentAndNotifyAccessibility(); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 378 | return; |
| 379 | case InsertText: |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 380 | insertTextAndNotifyAccessibility(m_textToInsert, m_selectInsertedText); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 381 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 382 | } |
| 383 | |
| 384 | ASSERT_NOT_REACHED(); |
| 385 | } |
| 386 | |
cdumez@apple.com | b5c30b7 | 2022-05-02 00:17:50 +0000 | [diff] [blame] | 387 | AtomString TypingCommand::inputEventTypeName() const |
wenson_hsieh@apple.com | 4bb2f7a | 2016-10-10 03:11:20 +0000 | [diff] [blame] | 388 | { |
| 389 | return inputTypeNameForEditingAction(m_currentTypingEditAction); |
| 390 | } |
| 391 | |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 392 | bool TypingCommand::isBeforeInputEventCancelable() const |
| 393 | { |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 394 | return m_currentTypingEditAction != EditAction::TypingInsertPendingComposition && m_currentTypingEditAction != EditAction::TypingDeletePendingComposition; |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 395 | } |
| 396 | |
wenson_hsieh@apple.com | 3747aa5 | 2016-10-10 18:30:03 +0000 | [diff] [blame] | 397 | String TypingCommand::inputEventData() const |
| 398 | { |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 399 | switch (m_currentTypingEditAction) { |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 400 | case EditAction::TypingInsertText: |
| 401 | case EditAction::TypingInsertPendingComposition: |
| 402 | case EditAction::TypingInsertFinalComposition: |
wenson_hsieh@apple.com | 3747aa5 | 2016-10-10 18:30:03 +0000 | [diff] [blame] | 403 | return m_currentTextToInsert; |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 404 | case EditAction::InsertReplacement: |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 405 | return isEditingTextAreaOrTextInput() ? m_currentTextToInsert : String(); |
wenson_hsieh@apple.com | 8ee483a | 2016-10-21 23:06:05 +0000 | [diff] [blame] | 406 | default: |
| 407 | return CompositeEditCommand::inputEventData(); |
| 408 | } |
wenson_hsieh@apple.com | 3747aa5 | 2016-10-10 18:30:03 +0000 | [diff] [blame] | 409 | } |
| 410 | |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 411 | RefPtr<DataTransfer> TypingCommand::inputEventDataTransfer() const |
| 412 | { |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 413 | if (m_currentTypingEditAction != EditAction::InsertReplacement || isEditingTextAreaOrTextInput()) |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 414 | return nullptr; |
| 415 | |
| 416 | StringBuilder htmlText; |
| 417 | MarkupAccumulator::appendCharactersReplacingEntities(htmlText, m_currentTextToInsert, 0, m_currentTextToInsert.length(), EntityMaskInHTMLPCDATA); |
cdumez@apple.com | c6e9e74 | 2019-09-18 22:30:39 +0000 | [diff] [blame] | 418 | return DataTransfer::createForInputEvent(m_currentTextToInsert, htmlText.toString()); |
wenson_hsieh@apple.com | adff4e0 | 2016-10-31 15:12:00 +0000 | [diff] [blame] | 419 | } |
| 420 | |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 421 | void TypingCommand::didApplyCommand() |
| 422 | { |
| 423 | // TypingCommands handle applied editing separately (see TypingCommand::typingAddedToOpenCommand). |
| 424 | m_isHandlingInitialTypingCommand = false; |
| 425 | } |
| 426 | |
commit-queue@webkit.org | 5766291 | 2010-09-29 00:14:17 +0000 | [diff] [blame] | 427 | void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 428 | { |
mitz@apple.com | 630ef44 | 2014-02-19 08:12:24 +0000 | [diff] [blame] | 429 | #if PLATFORM(MAC) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 430 | if (!document().editor().isContinuousSpellCheckingEnabled() |
| 431 | && !document().editor().isAutomaticQuoteSubstitutionEnabled() |
| 432 | && !document().editor().isAutomaticLinkDetectionEnabled() |
| 433 | && !document().editor().isAutomaticDashSubstitutionEnabled() |
| 434 | && !document().editor().isAutomaticTextReplacementEnabled()) |
andersca@apple.com | b417092 | 2013-05-15 19:47:47 +0000 | [diff] [blame] | 435 | return; |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 436 | if (document().editor().isHandlingAcceptedCandidate()) |
bdakin@apple.com | d84d6cb | 2016-02-04 00:01:46 +0000 | [diff] [blame] | 437 | return; |
justin.garcia@apple.com | 2ac9a81 | 2009-04-30 01:35:07 +0000 | [diff] [blame] | 438 | #else |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 439 | if (!document().editor().isContinuousSpellCheckingEnabled()) |
justin.garcia@apple.com | 6412551 | 2008-02-20 17:48:44 +0000 | [diff] [blame] | 440 | return; |
justin.garcia@apple.com | 2ac9a81 | 2009-04-30 01:35:07 +0000 | [diff] [blame] | 441 | #endif |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 442 | // Take a look at the selection that results after typing and determine whether we need to spellcheck. |
| 443 | // Since the word containing the current selection is never marked, this does a check to |
| 444 | // see if typing made a new word that is not in the current selection. Basically, you |
| 445 | // get this by being at the end of a word and typing a space. |
darin | 9aa45a4 | 2006-01-15 23:32:02 +0000 | [diff] [blame] | 446 | VisiblePosition start(endingSelection().start(), endingSelection().affinity()); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 447 | VisiblePosition previous = start.previous(); |
| 448 | if (previous.isNotNull()) { |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 449 | #if !PLATFORM(IOS_FAMILY) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 450 | VisiblePosition p1 = startOfWord(previous, LeftWordIfOnBoundary); |
| 451 | VisiblePosition p2 = startOfWord(start, LeftWordIfOnBoundary); |
commit-queue@webkit.org | 76bec61 | 2011-04-11 20:56:32 +0000 | [diff] [blame] | 452 | if (p1 != p2) { |
darin@apple.com | 5d3decc | 2020-08-01 15:50:36 +0000 | [diff] [blame] | 453 | auto range = makeSimpleRange(p1, p2); |
commit-queue@webkit.org | 76bec61 | 2011-04-11 20:56:32 +0000 | [diff] [blame] | 454 | String strippedPreviousWord; |
| 455 | if (range && (commandType == TypingCommand::InsertText || commandType == TypingCommand::InsertLineBreak || commandType == TypingCommand::InsertParagraphSeparator || commandType == TypingCommand::InsertParagraphSeparatorInQuotedContent)) |
darin@apple.com | 1b30f74 | 2020-04-02 18:57:15 +0000 | [diff] [blame] | 456 | strippedPreviousWord = plainText(*range).stripWhiteSpace(); |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 457 | document().editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), !strippedPreviousWord.isEmpty()); |
commit-queue@webkit.org | 76bec61 | 2011-04-11 20:56:32 +0000 | [diff] [blame] | 458 | } else if (commandType == TypingCommand::InsertText) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 459 | document().editor().startAlternativeTextUITimer(); |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 460 | #else |
| 461 | UNUSED_PARAM(commandType); |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 462 | // If this bug gets fixed, this PLATFORM(IOS_FAMILY) code could be removed: |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 463 | // <rdar://problem/7259611> Word boundary code on iPhone gives different results than desktop |
| 464 | EWordSide startWordSide = LeftWordIfOnBoundary; |
| 465 | UChar32 c = previous.characterAfter(); |
| 466 | // FIXME: VisiblePosition::characterAfter() and characterBefore() do not emit newlines the same |
| 467 | // way as TextIterator, so we do an isEndOfParagraph check here. |
darin@apple.com | 5917cb1 | 2017-11-23 17:32:42 +0000 | [diff] [blame] | 468 | if (isSpaceOrNewline(c) || c == noBreakSpace || isEndOfParagraph(previous)) { |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 469 | startWordSide = RightWordIfOnBoundary; |
| 470 | } |
| 471 | VisiblePosition p1 = startOfWord(previous, startWordSide); |
| 472 | VisiblePosition p2 = startOfWord(start, startWordSide); |
| 473 | if (p1 != p2) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 474 | document().editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), false); |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 475 | #endif // !PLATFORM(IOS_FAMILY) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 476 | } |
| 477 | } |
| 478 | |
darin@apple.com | a4ddc78 | 2021-05-30 16:11:40 +0000 | [diff] [blame] | 479 | bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity, const String& text, const std::optional<SimpleRange>& range) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 480 | { |
wenson_hsieh@apple.com | 3747aa5 | 2016-10-10 18:30:03 +0000 | [diff] [blame] | 481 | m_currentTextToInsert = text; |
wenson_hsieh@apple.com | a76d4f9c | 2016-10-29 01:06:13 +0000 | [diff] [blame] | 482 | m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity, m_compositionType, m_isAutocompletion); |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 483 | |
| 484 | if (!shouldDeferWillApplyCommandUntilAddingTypingCommand()) |
| 485 | return true; |
| 486 | |
| 487 | if (!range || isEditingTextAreaOrTextInput()) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 488 | return document().editor().willApplyEditing(*this, CompositeEditCommand::targetRangesForBindings()); |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 489 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 490 | return document().editor().willApplyEditing(*this, { 1, StaticRange::create(*range) }); |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 491 | } |
| 492 | |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 493 | void TypingCommand::typingAddedToOpenCommand(ETypingCommand commandTypeForAddedTyping) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 494 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 495 | RefPtr<Frame> protector(document().frame()); |
morrita@google.com | 7b933de | 2012-02-03 11:39:51 +0000 | [diff] [blame] | 496 | |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 497 | updatePreservesTypingStyle(commandTypeForAddedTyping); |
commit-queue@webkit.org | 5766291 | 2010-09-29 00:14:17 +0000 | [diff] [blame] | 498 | |
mitz@apple.com | 28c9d4a | 2014-02-08 22:26:50 +0000 | [diff] [blame] | 499 | #if PLATFORM(COCOA) |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 500 | document().editor().appliedEditing(*this); |
adele@apple.com | f4cbf34 | 2009-04-27 23:14:33 +0000 | [diff] [blame] | 501 | // Since the spellchecking code may also perform corrections and other replacements, it should happen after the typing changes. |
commit-queue@webkit.org | 6aedb68 | 2011-04-08 03:59:34 +0000 | [diff] [blame] | 502 | if (!m_shouldPreventSpellChecking) |
| 503 | markMisspellingsAfterTyping(commandTypeForAddedTyping); |
bdakin@apple.com | f2a17a7 | 2009-05-08 23:40:39 +0000 | [diff] [blame] | 504 | #else |
| 505 | // The old spellchecking code requires that checking be done first, to prevent issues like that in 6864072, where <doesn't> is marked as misspelled. |
commit-queue@webkit.org | 5766291 | 2010-09-29 00:14:17 +0000 | [diff] [blame] | 506 | markMisspellingsAfterTyping(commandTypeForAddedTyping); |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 507 | document().editor().appliedEditing(*this); |
bdakin@apple.com | f2a17a7 | 2009-05-08 23:40:39 +0000 | [diff] [blame] | 508 | #endif |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 509 | } |
| 510 | |
darin | b9481ed | 2006-03-20 02:57:59 +0000 | [diff] [blame] | 511 | void TypingCommand::insertText(const String &text, bool selectInsertedText) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 512 | { |
| 513 | // FIXME: Need to implement selectInsertedText for cases where more than one insert is involved. |
| 514 | // This requires support from insertTextRunWithoutNewlines and insertParagraphSeparator for extending |
| 515 | // an existing selection; at the moment they can either put the caret after what's inserted or |
| 516 | // select what's inserted, but there's no way to "extend selection" to include both an old selection |
| 517 | // that ends just before where we want to insert text and the newly inserted text. |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 518 | TypingCommandLineOperation operation(this, selectInsertedText, text); |
| 519 | forEachLineInString(text, operation); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 520 | } |
| 521 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 522 | void TypingCommand::insertTextAndNotifyAccessibility(const String &text, bool selectInsertedText) |
| 523 | { |
simon.fraser@apple.com | 906b086 | 2016-08-28 00:36:05 +0000 | [diff] [blame] | 524 | LOG(Editing, "TypingCommand %p insertTextAndNotifyAccessibility (text %s, selectInsertedText %d)", this, text.utf8().data(), selectInsertedText); |
| 525 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 526 | AccessibilityReplacedText replacedText(document().selection().selection()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 527 | insertText(text, selectInsertedText); |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 528 | replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, text, document().selection().selection()); |
d_russell@apple.com | d60eb24 | 2016-05-13 19:34:48 +0000 | [diff] [blame] | 529 | composition()->setRangeDeletedByUnapply(replacedText.replacedRange()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 530 | } |
| 531 | |
darin | b9481ed | 2006-03-20 02:57:59 +0000 | [diff] [blame] | 532 | void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 533 | { |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 534 | if (!willAddTypingToOpenCommand(InsertText, TextGranularity::CharacterGranularity, text)) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 535 | return; |
| 536 | |
cdumez@apple.com | 8f91d5b | 2017-05-01 18:08:07 +0000 | [diff] [blame] | 537 | auto command = InsertTextCommand::create(document(), text, selectInsertedText, |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 538 | m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces, EditAction::TypingInsertText); |
rniwa@webkit.org | 1a36430 | 2011-07-13 17:55:20 +0000 | [diff] [blame] | 539 | |
cdumez@apple.com | 8f91d5b | 2017-05-01 18:08:07 +0000 | [diff] [blame] | 540 | applyCommandToComposite(WTFMove(command), endingSelection()); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 541 | typingAddedToOpenCommand(InsertText); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 542 | } |
| 543 | |
| 544 | void TypingCommand::insertLineBreak() |
| 545 | { |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 546 | if (!canAppendNewLineFeedToSelection(endingSelection())) |
commit-queue@webkit.org | b887b8c | 2011-03-17 06:31:00 +0000 | [diff] [blame] | 547 | return; |
| 548 | |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 549 | if (!willAddTypingToOpenCommand(InsertLineBreak, TextGranularity::LineGranularity)) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 550 | return; |
| 551 | |
darin@apple.com | 48ac3c4 | 2008-06-14 08:46:51 +0000 | [diff] [blame] | 552 | applyCommandToComposite(InsertLineBreakCommand::create(document())); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 553 | typingAddedToOpenCommand(InsertLineBreak); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 554 | } |
| 555 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 556 | void TypingCommand::insertLineBreakAndNotifyAccessibility() |
| 557 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 558 | AccessibilityReplacedText replacedText(document().selection().selection()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 559 | insertLineBreak(); |
cdumez@apple.com | ec2f508 | 2022-03-28 21:20:09 +0000 | [diff] [blame] | 560 | replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n"_s, document().selection().selection()); |
d_russell@apple.com | d60eb24 | 2016-05-13 19:34:48 +0000 | [diff] [blame] | 561 | composition()->setRangeDeletedByUnapply(replacedText.replacedRange()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 562 | } |
| 563 | |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 564 | void TypingCommand::insertParagraphSeparator() |
| 565 | { |
jpu@apple.com | dfd2ce6 | 2012-04-16 03:05:06 +0000 | [diff] [blame] | 566 | if (!canAppendNewLineFeedToSelection(endingSelection())) |
commit-queue@webkit.org | b887b8c | 2011-03-17 06:31:00 +0000 | [diff] [blame] | 567 | return; |
| 568 | |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 569 | if (!willAddTypingToOpenCommand(InsertParagraphSeparator, TextGranularity::ParagraphGranularity)) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 570 | return; |
| 571 | |
wenson_hsieh@apple.com | ea09101 | 2018-09-07 03:04:53 +0000 | [diff] [blame] | 572 | applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), false, false, EditAction::TypingInsertParagraph)); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 573 | typingAddedToOpenCommand(InsertParagraphSeparator); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 574 | } |
| 575 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 576 | void TypingCommand::insertParagraphSeparatorAndNotifyAccessibility() |
| 577 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 578 | AccessibilityReplacedText replacedText(document().selection().selection()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 579 | insertParagraphSeparator(); |
cdumez@apple.com | ec2f508 | 2022-03-28 21:20:09 +0000 | [diff] [blame] | 580 | replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n"_s, document().selection().selection()); |
d_russell@apple.com | d60eb24 | 2016-05-13 19:34:48 +0000 | [diff] [blame] | 581 | composition()->setRangeDeletedByUnapply(replacedText.replacedRange()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 582 | } |
| 583 | |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 584 | void TypingCommand::insertParagraphSeparatorInQuotedContent() |
| 585 | { |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 586 | if (!willAddTypingToOpenCommand(InsertParagraphSeparatorInQuotedContent, TextGranularity::ParagraphGranularity)) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 587 | return; |
| 588 | |
adele@apple.com | 65426e3 | 2009-04-12 05:49:44 +0000 | [diff] [blame] | 589 | // If the selection starts inside a table, just insert the paragraph separator normally |
| 590 | // Breaking the blockquote would also break apart the table, which is unecessary when inserting a newline |
| 591 | if (enclosingNodeOfType(endingSelection().start(), &isTableStructureNode)) { |
| 592 | insertParagraphSeparator(); |
| 593 | return; |
| 594 | } |
| 595 | |
darin@apple.com | 48ac3c4 | 2008-06-14 08:46:51 +0000 | [diff] [blame] | 596 | applyCommandToComposite(BreakBlockquoteCommand::create(document())); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 597 | typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 598 | } |
| 599 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 600 | void TypingCommand::insertParagraphSeparatorInQuotedContentAndNotifyAccessibility() |
| 601 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 602 | AccessibilityReplacedText replacedText(document().selection().selection()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 603 | insertParagraphSeparatorInQuotedContent(); |
cdumez@apple.com | ec2f508 | 2022-03-28 21:20:09 +0000 | [diff] [blame] | 604 | replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n"_s, document().selection().selection()); |
d_russell@apple.com | d60eb24 | 2016-05-13 19:34:48 +0000 | [diff] [blame] | 605 | composition()->setRangeDeletedByUnapply(replacedText.replacedRange()); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 606 | } |
| 607 | |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 608 | bool TypingCommand::makeEditableRootEmpty() |
| 609 | { |
| 610 | Element* root = endingSelection().rootEditableElement(); |
eae@chromium.org | 480a442 | 2011-03-29 12:10:05 +0000 | [diff] [blame] | 611 | if (!root || !root->firstChild()) |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 612 | return false; |
| 613 | |
| 614 | if (root->firstChild() == root->lastChild() && root->firstElementChild() && root->firstElementChild()->hasTagName(brTag)) { |
| 615 | // If there is a single child and it could be a placeholder, leave it alone. |
hyatt@apple.com | 7caec52 | 2013-09-09 18:37:33 +0000 | [diff] [blame] | 616 | if (root->renderer() && root->renderer()->isRenderBlockFlow()) |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 617 | return false; |
| 618 | } |
| 619 | |
| 620 | while (Node* child = root->firstChild()) |
cdumez@apple.com | 2fecce7 | 2017-05-05 05:09:56 +0000 | [diff] [blame] | 621 | removeNode(*child); |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 622 | |
| 623 | addBlockPlaceholderIfNeeded(root); |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 624 | setEndingSelection(VisibleSelection(firstPositionInNode(root), Affinity::Downstream, endingSelection().isDirectional())); |
mitz@apple.com | 3d9a508 | 2009-04-30 03:03:29 +0000 | [diff] [blame] | 625 | |
| 626 | return true; |
| 627 | } |
| 628 | |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 629 | void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 630 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 631 | RefPtr<Frame> protector(document().frame()); |
morrita@google.com | 7b933de | 2012-02-03 11:39:51 +0000 | [diff] [blame] | 632 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 633 | document().editor().updateMarkersForWordsAffectedByEditing(false); |
morrita@google.com | 4e40c8b | 2011-04-08 21:21:44 +0000 | [diff] [blame] | 634 | |
eric@webkit.org | 87ea95c | 2009-02-09 21:43:24 +0000 | [diff] [blame] | 635 | VisibleSelection selectionToDelete; |
| 636 | VisibleSelection selectionAfterUndo; |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 637 | bool expandForSpecialElements = false; |
commit-queue@webkit.org | 08abac6 | 2010-10-28 23:45:26 +0000 | [diff] [blame] | 638 | |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 639 | ASSERT(endingSelection().isCaretOrRange()); |
| 640 | |
| 641 | if (endingSelection().isRange()) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 642 | selectionToDelete = endingSelection(); |
| 643 | selectionAfterUndo = selectionToDelete; |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 644 | expandForSpecialElements = true; |
| 645 | } else { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 646 | // After breaking out of an empty mail blockquote, we still want continue with the deletion |
| 647 | // so actual content will get deleted, and not just the quote style. |
| 648 | if (breakOutOfEmptyMailBlockquotedParagraph()) |
| 649 | typingAddedToOpenCommand(DeleteKey); |
darin | d4408fc | 2007-04-24 17:37:50 +0000 | [diff] [blame] | 650 | |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 651 | m_smartDelete = false; |
enrica@apple.com | bde8a9a | 2009-12-15 01:14:35 +0000 | [diff] [blame] | 652 | |
rniwa@webkit.org | 78bbc94 | 2011-05-05 18:14:43 +0000 | [diff] [blame] | 653 | FrameSelection selection; |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 654 | selection.setSelection(endingSelection()); |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 655 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Backward, granularity); |
| 656 | if (shouldAddToKillRing && selection.isCaret() && granularity != TextGranularity::CharacterGranularity) |
| 657 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Backward, TextGranularity::CharacterGranularity); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 658 | |
jfernandez@igalia.com | 4bb32e8 | 2017-08-08 12:22:33 +0000 | [diff] [blame] | 659 | const VisiblePosition& visibleStart = endingSelection().visibleStart(); |
| 660 | const VisiblePosition& previousPosition = visibleStart.previous(CannotCrossEditingBoundary); |
| 661 | Node* enclosingTableCell = enclosingNodeOfType(visibleStart.deepEquivalent(), &isTableCell); |
| 662 | const Node* enclosingTableCellForPreviousPosition = enclosingNodeOfType(previousPosition.deepEquivalent(), &isTableCell); |
| 663 | if (previousPosition.isNull() || enclosingTableCell != enclosingTableCellForPreviousPosition) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 664 | // When the caret is at the start of the editable area in an empty list item, break out of the list item. |
commit-queue@webkit.org | ff9eed3 | 2021-08-31 08:39:52 +0000 | [diff] [blame] | 665 | if (auto deleteListSelection = shouldBreakOutOfEmptyListItem(); !deleteListSelection.isNone()) { |
| 666 | if (willAddTypingToOpenCommand(DeleteKey, granularity, { }, deleteListSelection.firstRange())) { |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 667 | breakOutOfEmptyListItem(); |
| 668 | typingAddedToOpenCommand(DeleteKey); |
| 669 | } |
lweintraub | 6d37780 | 2006-07-07 19:33:28 +0000 | [diff] [blame] | 670 | return; |
| 671 | } |
jfernandez@igalia.com | 4bb32e8 | 2017-08-08 12:22:33 +0000 | [diff] [blame] | 672 | } |
| 673 | if (previousPosition.isNull()) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 674 | // When there are no visible positions in the editing root, delete its entire contents. |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 675 | // FIXME: Dispatch a `beforeinput` event here and bail if preventDefault() was invoked. |
jfernandez@igalia.com | 4bb32e8 | 2017-08-08 12:22:33 +0000 | [diff] [blame] | 676 | if (visibleStart.next(CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty()) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 677 | typingAddedToOpenCommand(DeleteKey); |
| 678 | return; |
ap@webkit.org | ee2987b | 2008-12-10 12:49:56 +0000 | [diff] [blame] | 679 | } |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 680 | } |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 681 | |
commit-queue@webkit.org | 66c34e4 | 2013-03-15 04:25:27 +0000 | [diff] [blame] | 682 | // If we have a caret selection at the beginning of a cell, we have nothing to do. |
commit-queue@webkit.org | 66c34e4 | 2013-03-15 04:25:27 +0000 | [diff] [blame] | 683 | if (enclosingTableCell && visibleStart == firstPositionInNode(enclosingTableCell)) |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 684 | return; |
| 685 | |
| 686 | // If the caret is at the start of a paragraph after a table, move content into the last table cell. |
rniwa@webkit.org | ea702ba | 2011-03-10 21:15:45 +0000 | [diff] [blame] | 687 | if (isStartOfParagraph(visibleStart) && isFirstPositionAfterTable(visibleStart.previous(CannotCrossEditingBoundary))) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 688 | // Unless the caret is just before a table. We don't want to move a table into the last table cell. |
| 689 | if (isLastPositionBeforeTable(visibleStart)) |
| 690 | return; |
| 691 | // Extend the selection backward into the last cell, then deletion will handle the move. |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 692 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Backward, granularity); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 693 | // If the caret is just after a table, select the table and don't delete anything. |
| 694 | } else if (Node* table = isFirstPositionAfterTable(visibleStart)) { |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 695 | setEndingSelection(VisibleSelection(positionBeforeNode(table), endingSelection().start(), Affinity::Downstream, endingSelection().isDirectional())); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 696 | typingAddedToOpenCommand(DeleteKey); |
| 697 | return; |
| 698 | } |
| 699 | |
| 700 | selectionToDelete = selection.selection(); |
| 701 | |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 702 | if (granularity == TextGranularity::CharacterGranularity && selectionToDelete.end().containerNode() == selectionToDelete.start().containerNode() |
rniwa@webkit.org | 5b6a752 | 2011-04-20 01:18:03 +0000 | [diff] [blame] | 703 | && selectionToDelete.end().computeOffsetInContainerNode() - selectionToDelete.start().computeOffsetInContainerNode() > 1) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 704 | // If there are multiple Unicode code points to be deleted, adjust the range to match platform conventions. |
| 705 | selectionToDelete.setWithoutValidation(selectionToDelete.end(), selectionToDelete.end().previous(BackwardDeletion)); |
| 706 | } |
| 707 | |
| 708 | if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start()) |
| 709 | selectionAfterUndo = selectionToDelete; |
| 710 | else |
| 711 | // It's a little tricky to compute what the starting selection would have been in the original document. |
| 712 | // We can't let the VisibleSelection class's validation kick in or it'll adjust for us based on |
| 713 | // the current state of the document and we'll get the wrong result. |
| 714 | selectionAfterUndo.setWithoutValidation(startingSelection().end(), selectionToDelete.extent()); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 715 | } |
| 716 | |
justin.garcia@apple.com | 313f215 | 2009-03-06 01:25:40 +0000 | [diff] [blame] | 717 | ASSERT(!selectionToDelete.isNone()); |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 718 | if (selectionToDelete.isNone()) { |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 719 | #if PLATFORM(IOS_FAMILY) |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 720 | // Workaround for this bug: |
| 721 | // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 722 | setEndingSelection(document().selection().selection()); |
| 723 | closeTyping(document()); |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 724 | #endif |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 725 | return; |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 726 | } |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 727 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 728 | if (selectionToDelete.isCaret() || !document().selection().shouldDeleteSelection(selectionToDelete)) |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 729 | return; |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 730 | |
darin@apple.com | 5d3decc | 2020-08-01 15:50:36 +0000 | [diff] [blame] | 731 | if (!willAddTypingToOpenCommand(DeleteKey, granularity, { }, selectionToDelete.firstRange())) |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 732 | return; |
| 733 | |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 734 | if (shouldAddToKillRing) |
darin@apple.com | f91ef17 | 2020-08-03 00:47:52 +0000 | [diff] [blame] | 735 | document().editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange(), Editor::KillRingInsertionMode::PrependText); |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 736 | |
| 737 | // Post the accessibility notification before actually deleting the content while selectionToDelete is still valid |
| 738 | postTextStateChangeNotificationForDeletion(selectionToDelete); |
| 739 | |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 740 | // Make undo select everything that has been deleted, unless an undo will undo more than just this deletion. |
| 741 | // FIXME: This behaves like TextEdit except for the case where you open with text insertion and then delete |
| 742 | // more text than you insert. In that case all of the text that was around originally should be selected. |
| 743 | if (m_openedByBackwardDelete) |
| 744 | setStartingSelection(selectionAfterUndo); |
jfernandez@igalia.com | 736db5b | 2018-07-17 08:48:49 +0000 | [diff] [blame] | 745 | CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete, /* mergeBlocksAfterDelete*/ true, /* replace*/ false, expandForSpecialElements, /*sanitizeMarkup*/ true); |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 746 | setSmartDelete(false); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 747 | typingAddedToOpenCommand(DeleteKey); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 748 | } |
| 749 | |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 750 | void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 751 | { |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 752 | RefPtr<Frame> protector(document().frame()); |
morrita@google.com | 7b933de | 2012-02-03 11:39:51 +0000 | [diff] [blame] | 753 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 754 | document().editor().updateMarkersForWordsAffectedByEditing(false); |
morrita@google.com | 4e40c8b | 2011-04-08 21:21:44 +0000 | [diff] [blame] | 755 | |
eric@webkit.org | 87ea95c | 2009-02-09 21:43:24 +0000 | [diff] [blame] | 756 | VisibleSelection selectionToDelete; |
| 757 | VisibleSelection selectionAfterUndo; |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 758 | bool expandForSpecialElements = false; |
darin | d4408fc | 2007-04-24 17:37:50 +0000 | [diff] [blame] | 759 | |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 760 | ASSERT(endingSelection().isCaretOrRange()); |
| 761 | |
| 762 | if (endingSelection().isRange()) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 763 | selectionToDelete = endingSelection(); |
| 764 | selectionAfterUndo = selectionToDelete; |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 765 | expandForSpecialElements = true; |
| 766 | } else { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 767 | m_smartDelete = false; |
darin | d4408fc | 2007-04-24 17:37:50 +0000 | [diff] [blame] | 768 | |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 769 | // Handle delete at beginning-of-block case. |
| 770 | // Do nothing in the case that the caret is at the start of a |
| 771 | // root editable element or at the start of a document. |
rniwa@webkit.org | 78bbc94 | 2011-05-05 18:14:43 +0000 | [diff] [blame] | 772 | FrameSelection selection; |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 773 | selection.setSelection(endingSelection()); |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 774 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Forward, granularity); |
shihchieh_lee@apple.com | da81f1e | 2020-04-15 21:57:22 +0000 | [diff] [blame] | 775 | if (selection.isNone()) |
| 776 | return; |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 777 | if (shouldAddToKillRing && selection.isCaret() && granularity != TextGranularity::CharacterGranularity) |
| 778 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Forward, TextGranularity::CharacterGranularity); |
harrison | 5eb1599 | 2006-12-20 15:40:34 +0000 | [diff] [blame] | 779 | |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 780 | Position downstreamEnd = endingSelection().end().downstream(); |
| 781 | VisiblePosition visibleEnd = endingSelection().visibleEnd(); |
commit-queue@webkit.org | 66c34e4 | 2013-03-15 04:25:27 +0000 | [diff] [blame] | 782 | Node* enclosingTableCell = enclosingNodeOfType(visibleEnd.deepEquivalent(), &isTableCell); |
| 783 | if (enclosingTableCell && visibleEnd == lastPositionInNode(enclosingTableCell)) |
commit-queue@webkit.org | b38d513 | 2012-07-30 05:22:58 +0000 | [diff] [blame] | 784 | return; |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 785 | if (visibleEnd == endOfParagraph(visibleEnd)) |
rniwa@webkit.org | ea702ba | 2011-03-10 21:15:45 +0000 | [diff] [blame] | 786 | downstreamEnd = visibleEnd.next(CannotCrossEditingBoundary).deepEquivalent().downstream(); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 787 | // When deleting tables: Select the table first, then perform the deletion |
rniwa@webkit.org | 5b6a752 | 2011-04-20 01:18:03 +0000 | [diff] [blame] | 788 | if (downstreamEnd.containerNode() && downstreamEnd.containerNode()->renderer() && downstreamEnd.containerNode()->renderer()->isTable() |
darin@apple.com | d385be4 | 2016-05-14 20:09:50 +0000 | [diff] [blame] | 789 | && downstreamEnd.computeOffsetInContainerNode() <= caretMinOffset(*downstreamEnd.containerNode())) { |
darin@apple.com | c8d8b55 | 2020-09-03 21:38:50 +0000 | [diff] [blame] | 790 | setEndingSelection(VisibleSelection(endingSelection().end(), positionAfterNode(downstreamEnd.containerNode()), Affinity::Downstream, endingSelection().isDirectional())); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 791 | typingAddedToOpenCommand(ForwardDeleteKey); |
| 792 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 793 | } |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 794 | |
| 795 | // deleting to end of paragraph when at end of paragraph needs to merge the next paragraph (if any) |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 796 | if (granularity == TextGranularity::ParagraphBoundary && selection.selection().isCaret() && isEndOfParagraph(selection.selection().visibleEnd())) |
| 797 | selection.modify(FrameSelection::AlterationExtend, SelectionDirection::Forward, TextGranularity::CharacterGranularity); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 798 | |
| 799 | selectionToDelete = selection.selection(); |
| 800 | if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start()) |
| 801 | selectionAfterUndo = selectionToDelete; |
| 802 | else { |
| 803 | // It's a little tricky to compute what the starting selection would have been in the original document. |
| 804 | // We can't let the VisibleSelection class's validation kick in or it'll adjust for us based on |
| 805 | // the current state of the document and we'll get the wrong result. |
| 806 | Position extent = startingSelection().end(); |
rniwa@webkit.org | 5b6a752 | 2011-04-20 01:18:03 +0000 | [diff] [blame] | 807 | if (extent.containerNode() != selectionToDelete.end().containerNode()) |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 808 | extent = selectionToDelete.extent(); |
| 809 | else { |
| 810 | int extraCharacters; |
rniwa@webkit.org | 5b6a752 | 2011-04-20 01:18:03 +0000 | [diff] [blame] | 811 | if (selectionToDelete.start().containerNode() == selectionToDelete.end().containerNode()) |
| 812 | extraCharacters = selectionToDelete.end().computeOffsetInContainerNode() - selectionToDelete.start().computeOffsetInContainerNode(); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 813 | else |
rniwa@webkit.org | 5b6a752 | 2011-04-20 01:18:03 +0000 | [diff] [blame] | 814 | extraCharacters = selectionToDelete.end().computeOffsetInContainerNode(); |
| 815 | extent = Position(extent.containerNode(), extent.computeOffsetInContainerNode() + extraCharacters, Position::PositionIsOffsetInAnchor); |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 816 | } |
| 817 | selectionAfterUndo.setWithoutValidation(startingSelection().start(), extent); |
| 818 | } |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 819 | } |
| 820 | |
justin.garcia@apple.com | 313f215 | 2009-03-06 01:25:40 +0000 | [diff] [blame] | 821 | ASSERT(!selectionToDelete.isNone()); |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 822 | if (selectionToDelete.isNone()) { |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 823 | #if PLATFORM(IOS_FAMILY) |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 824 | // Workaround for this bug: |
| 825 | // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 826 | setEndingSelection(document().selection().selection()); |
| 827 | closeTyping(document()); |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 828 | #endif |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 829 | return; |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 830 | } |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 831 | |
shihchieh_lee@apple.com | 501b37c | 2020-04-28 16:36:38 +0000 | [diff] [blame] | 832 | if (selectionToDelete.isCaret() || !document().selection().shouldDeleteSelection(selectionToDelete)) |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 833 | return; |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 834 | |
darin@apple.com | 5d3decc | 2020-08-01 15:50:36 +0000 | [diff] [blame] | 835 | if (!willAddTypingToOpenCommand(ForwardDeleteKey, granularity, { }, selectionToDelete.firstRange())) |
wenson_hsieh@apple.com | 6ed4b15 | 2016-10-21 15:51:28 +0000 | [diff] [blame] | 836 | return; |
| 837 | |
d_russell@apple.com | 07f8559 | 2016-04-04 23:17:59 +0000 | [diff] [blame] | 838 | // Post the accessibility notification before actually deleting the content while selectionToDelete is still valid |
| 839 | postTextStateChangeNotificationForDeletion(selectionToDelete); |
| 840 | |
bburg@apple.com | f4fb5bb | 2015-11-19 19:29:59 +0000 | [diff] [blame] | 841 | if (shouldAddToKillRing) |
darin@apple.com | f91ef17 | 2020-08-03 00:47:52 +0000 | [diff] [blame] | 842 | document().editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange(), Editor::KillRingInsertionMode::AppendText); |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 843 | // make undo select what was deleted |
| 844 | setStartingSelection(selectionAfterUndo); |
jfernandez@igalia.com | 736db5b | 2018-07-17 08:48:49 +0000 | [diff] [blame] | 845 | CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete, /* mergeBlocksAfterDelete*/ true, /* replace*/ false, expandForSpecialElements, /*sanitizeMarkup*/ true); |
justin.garcia@apple.com | 0e8bd79 | 2009-03-06 01:00:29 +0000 | [diff] [blame] | 846 | setSmartDelete(false); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 847 | typingAddedToOpenCommand(ForwardDeleteKey); |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 848 | } |
| 849 | |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 850 | void TypingCommand::deleteSelection(bool smartDelete) |
| 851 | { |
commit-queue@webkit.org | 2dd3588 | 2020-05-16 03:45:59 +0000 | [diff] [blame] | 852 | if (!willAddTypingToOpenCommand(DeleteSelection, TextGranularity::CharacterGranularity)) |
wenson_hsieh@apple.com | 2bebcde | 2016-10-07 23:47:18 +0000 | [diff] [blame] | 853 | return; |
| 854 | |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 855 | CompositeEditCommand::deleteSelection(smartDelete); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 856 | typingAddedToOpenCommand(DeleteSelection); |
justing | ee38ac8 | 2007-10-25 00:58:54 +0000 | [diff] [blame] | 857 | } |
| 858 | |
ap@apple.com | 1e847592 | 2018-10-18 21:38:50 +0000 | [diff] [blame] | 859 | #if PLATFORM(IOS_FAMILY) |
dbates@webkit.org | f435ee1 | 2014-01-10 17:06:52 +0000 | [diff] [blame] | 860 | class FriendlyEditCommand : public EditCommand { |
| 861 | public: |
| 862 | void setEndingSelection(const VisibleSelection& selection) |
| 863 | { |
| 864 | EditCommand::setEndingSelection(selection); |
| 865 | } |
| 866 | }; |
| 867 | |
| 868 | void TypingCommand::setEndingSelectionOnLastInsertCommand(const VisibleSelection& selection) |
| 869 | { |
| 870 | if (!m_commands.isEmpty()) { |
| 871 | EditCommand* lastCommand = m_commands.last().get(); |
| 872 | if (lastCommand->isInsertTextCommand()) |
| 873 | static_cast<FriendlyEditCommand*>(lastCommand)->setEndingSelection(selection); |
| 874 | } |
| 875 | } |
| 876 | #endif |
| 877 | |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 878 | void TypingCommand::updatePreservesTypingStyle(ETypingCommand commandType) |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 879 | { |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 880 | switch (commandType) { |
eric@webkit.org | b0988e2 | 2010-05-31 00:51:55 +0000 | [diff] [blame] | 881 | case DeleteSelection: |
| 882 | case DeleteKey: |
| 883 | case ForwardDeleteKey: |
| 884 | case InsertParagraphSeparator: |
| 885 | case InsertLineBreak: |
| 886 | m_preservesTypingStyle = true; |
| 887 | return; |
| 888 | case InsertParagraphSeparatorInQuotedContent: |
| 889 | case InsertText: |
| 890 | m_preservesTypingStyle = false; |
| 891 | return; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 892 | } |
| 893 | ASSERT_NOT_REACHED(); |
adele@apple.com | 03d6c3a | 2009-06-26 16:53:24 +0000 | [diff] [blame] | 894 | m_preservesTypingStyle = false; |
mjs | 84e724c | 2005-05-24 07:21:47 +0000 | [diff] [blame] | 895 | } |
| 896 | |
| 897 | bool TypingCommand::isTypingCommand() const |
| 898 | { |
| 899 | return true; |
| 900 | } |
| 901 | |
darin | b9481ed | 2006-03-20 02:57:59 +0000 | [diff] [blame] | 902 | } // namespace WebCore |