1 | /* |
2 | * Copyright (C) 2005, 2006, 2007, 2013 Apple, Inc. All rights reserved. |
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 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
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 | |
26 | #include "config.h" |
27 | #include "EditCommand.h" |
28 | |
29 | #include "AXObjectCache.h" |
30 | #include "CompositeEditCommand.h" |
31 | #include "Document.h" |
32 | #include "Editing.h" |
33 | #include "Editor.h" |
34 | #include "Element.h" |
35 | #include "Frame.h" |
36 | #include "HTMLInputElement.h" |
37 | #include "HTMLTextAreaElement.h" |
38 | #include "NodeTraversal.h" |
39 | |
40 | namespace WebCore { |
41 | |
42 | String inputTypeNameForEditingAction(EditAction action) |
43 | { |
44 | switch (action) { |
45 | case EditAction::Justify: |
46 | return "formatJustifyFull"_s ; |
47 | case EditAction::AlignLeft: |
48 | return "formatJustifyLeft"_s ; |
49 | case EditAction::AlignRight: |
50 | return "formatJustifyRight"_s ; |
51 | case EditAction::Center: |
52 | return "formatJustifyCenter"_s ; |
53 | case EditAction::Subscript: |
54 | return "formatSubscript"_s ; |
55 | case EditAction::Superscript: |
56 | return "formatSuperscript"_s ; |
57 | case EditAction::Underline: |
58 | return "formatUnderline"_s ; |
59 | case EditAction::SetColor: |
60 | return "formatFontColor"_s ; |
61 | case EditAction::DeleteByDrag: |
62 | return "deleteByDrag"_s ; |
63 | case EditAction::Cut: |
64 | return "deleteByCut"_s ; |
65 | case EditAction::Bold: |
66 | return "formatBold"_s ; |
67 | case EditAction::Italics: |
68 | return "formatItalic"_s ; |
69 | case EditAction::Paste: |
70 | return "insertFromPaste"_s ; |
71 | case EditAction::Delete: |
72 | case EditAction::TypingDeleteSelection: |
73 | return "deleteContent"_s ; |
74 | case EditAction::TypingDeleteBackward: |
75 | return "deleteContentBackward"_s ; |
76 | case EditAction::TypingDeleteForward: |
77 | return "deleteContentForward"_s ; |
78 | case EditAction::TypingDeleteWordBackward: |
79 | return "deleteWordBackward"_s ; |
80 | case EditAction::TypingDeleteWordForward: |
81 | return "deleteWordForward"_s ; |
82 | case EditAction::TypingDeleteLineBackward: |
83 | return "deleteHardLineBackward"_s ; |
84 | case EditAction::TypingDeleteLineForward: |
85 | return "deleteHardLineForward"_s ; |
86 | case EditAction::TypingDeletePendingComposition: |
87 | return "deleteCompositionText"_s ; |
88 | case EditAction::TypingDeleteFinalComposition: |
89 | return "deleteByComposition"_s ; |
90 | case EditAction::Insert: |
91 | case EditAction::TypingInsertText: |
92 | return "insertText"_s ; |
93 | case EditAction::InsertReplacement: |
94 | return "insertReplacementText"_s ; |
95 | case EditAction::InsertFromDrop: |
96 | return "insertFromDrop"_s ; |
97 | case EditAction::TypingInsertLineBreak: |
98 | return "insertLineBreak"_s ; |
99 | case EditAction::TypingInsertParagraph: |
100 | return "insertParagraph"_s ; |
101 | case EditAction::InsertOrderedList: |
102 | return "insertOrderedList"_s ; |
103 | case EditAction::InsertUnorderedList: |
104 | return "insertUnorderedList"_s ; |
105 | case EditAction::TypingInsertPendingComposition: |
106 | return "insertCompositionText"_s ; |
107 | case EditAction::TypingInsertFinalComposition: |
108 | return "insertFromComposition"_s ; |
109 | case EditAction::Indent: |
110 | return "formatIndent"_s ; |
111 | case EditAction::Outdent: |
112 | return "formatOutdent"_s ; |
113 | case EditAction::SetInlineWritingDirection: |
114 | return "formatSetInlineTextDirection"_s ; |
115 | case EditAction::SetBlockWritingDirection: |
116 | return "formatSetBlockTextDirection"_s ; |
117 | default: |
118 | return emptyString(); |
119 | } |
120 | } |
121 | |
122 | EditCommand::EditCommand(Document& document, EditAction editingAction) |
123 | : m_document(document) |
124 | , m_editingAction(editingAction) |
125 | { |
126 | ASSERT(document.frame()); |
127 | setStartingSelection(m_document->frame()->selection().selection()); |
128 | setEndingSelection(m_startingSelection); |
129 | } |
130 | |
131 | EditCommand::EditCommand(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection) |
132 | : m_document(document) |
133 | { |
134 | ASSERT(document.frame()); |
135 | setStartingSelection(startingSelection); |
136 | setEndingSelection(endingSelection); |
137 | } |
138 | |
139 | EditCommand::~EditCommand() = default; |
140 | |
141 | Frame& EditCommand::frame() |
142 | { |
143 | ASSERT(document().frame()); |
144 | return *document().frame(); |
145 | } |
146 | |
147 | const Frame& EditCommand::frame() const |
148 | { |
149 | ASSERT(document().frame()); |
150 | return *document().frame(); |
151 | } |
152 | |
153 | EditAction EditCommand::editingAction() const |
154 | { |
155 | return m_editingAction; |
156 | } |
157 | |
158 | static inline EditCommandComposition* compositionIfPossible(EditCommand* command) |
159 | { |
160 | if (!command->isCompositeEditCommand()) |
161 | return 0; |
162 | return toCompositeEditCommand(command)->composition(); |
163 | } |
164 | |
165 | bool EditCommand::isEditingTextAreaOrTextInput() const |
166 | { |
167 | auto* frame = m_document->frame(); |
168 | if (!frame) |
169 | return false; |
170 | |
171 | auto* container = frame->selection().selection().start().containerNode(); |
172 | if (!container) |
173 | return false; |
174 | |
175 | auto* ancestor = container->shadowHost(); |
176 | if (!ancestor) |
177 | return false; |
178 | |
179 | return is<HTMLTextAreaElement>(*ancestor) || (is<HTMLInputElement>(*ancestor) && downcast<HTMLInputElement>(*ancestor).isText()); |
180 | } |
181 | |
182 | void EditCommand::setStartingSelection(const VisibleSelection& s) |
183 | { |
184 | for (EditCommand* cmd = this; ; cmd = cmd->m_parent) { |
185 | if (auto* composition = compositionIfPossible(cmd)) |
186 | composition->setStartingSelection(s); |
187 | cmd->m_startingSelection = s; |
188 | if (!cmd->m_parent || cmd->m_parent->isFirstCommand(cmd)) |
189 | break; |
190 | } |
191 | } |
192 | |
193 | void EditCommand::setEndingSelection(const VisibleSelection &s) |
194 | { |
195 | for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) { |
196 | if (auto* composition = compositionIfPossible(cmd)) |
197 | composition->setEndingSelection(s); |
198 | cmd->m_endingSelection = s; |
199 | } |
200 | } |
201 | |
202 | void EditCommand::setParent(CompositeEditCommand* parent) |
203 | { |
204 | ASSERT((parent && !m_parent) || (!parent && m_parent)); |
205 | m_parent = parent; |
206 | if (parent) { |
207 | m_startingSelection = parent->m_endingSelection; |
208 | m_endingSelection = parent->m_endingSelection; |
209 | } |
210 | } |
211 | |
212 | void EditCommand::postTextStateChangeNotification(AXTextEditType type, const String& text) |
213 | { |
214 | if (!AXObjectCache::accessibilityEnabled()) |
215 | return; |
216 | postTextStateChangeNotification(type, text, frame().selection().selection().start()); |
217 | } |
218 | |
219 | void EditCommand::postTextStateChangeNotification(AXTextEditType type, const String& text, const VisiblePosition& position) |
220 | { |
221 | if (!AXObjectCache::accessibilityEnabled()) |
222 | return; |
223 | if (!text.length()) |
224 | return; |
225 | auto* cache = document().existingAXObjectCache(); |
226 | if (!cache) |
227 | return; |
228 | auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole); |
229 | cache->postTextStateChangeNotification(node, type, text, position); |
230 | } |
231 | |
232 | SimpleEditCommand::SimpleEditCommand(Document& document, EditAction editingAction) |
233 | : EditCommand(document, editingAction) |
234 | { |
235 | } |
236 | |
237 | void SimpleEditCommand::doReapply() |
238 | { |
239 | doApply(); |
240 | } |
241 | |
242 | #ifndef NDEBUG |
243 | void SimpleEditCommand::addNodeAndDescendants(Node* startNode, HashSet<Node*>& nodes) |
244 | { |
245 | for (Node* node = startNode; node; node = NodeTraversal::next(*node, startNode)) |
246 | nodes.add(node); |
247 | } |
248 | #endif |
249 | |
250 | } // namespace WebCore |
251 | |