blob: daa77e46cec6178fe43f4230aa37fb89a18ebee8 [file] [log] [blame]
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001/*
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Ben Murdoch02772c62013-07-26 10:21:05 +010024 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010025 */
26
27#include "config.h"
28#include "core/editing/Editor.h"
29
30#include "CSSPropertyNames.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010031#include "HTMLNames.h"
Ben Murdochdf957042013-08-06 11:01:27 +010032#include "bindings/v8/ExceptionStatePlaceholder.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010033#include "core/accessibility/AXObjectCache.h"
34#include "core/css/CSSComputedStyleDeclaration.h"
35#include "core/css/StylePropertySet.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010036#include "core/dom/Clipboard.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010037#include "core/dom/DocumentFragment.h"
38#include "core/dom/DocumentMarkerController.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010039#include "core/dom/NodeList.h"
40#include "core/dom/NodeTraversal.h"
Torne (Richard Coles)1e202182013-10-18 15:46:42 +010041#include "core/dom/ParserContentPolicy.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010042#include "core/dom/Text.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010043#include "core/editing/ApplyStyleCommand.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010044#include "core/editing/DeleteSelectionCommand.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010045#include "core/editing/IndentOutdentCommand.h"
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +010046#include "core/editing/InputMethodController.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010047#include "core/editing/InsertListCommand.h"
48#include "core/editing/ModifySelectionListLevel.h"
49#include "core/editing/RemoveFormatCommand.h"
50#include "core/editing/RenderedPosition.h"
51#include "core/editing/ReplaceSelectionCommand.h"
52#include "core/editing/SimplifyMarkupCommand.h"
Torne (Richard Coles)1e202182013-10-18 15:46:42 +010053#include "core/editing/SpellChecker.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010054#include "core/editing/TextIterator.h"
55#include "core/editing/TypingCommand.h"
Torne (Richard Coles)51b29062013-11-28 11:56:03 +000056#include "core/editing/UndoStack.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010057#include "core/editing/VisibleUnits.h"
58#include "core/editing/htmlediting.h"
59#include "core/editing/markup.h"
Torne (Richard Coles)1e202182013-10-18 15:46:42 +010060#include "core/events/ClipboardEvent.h"
61#include "core/events/KeyboardEvent.h"
62#include "core/events/ScopedEventQueue.h"
63#include "core/events/TextEvent.h"
64#include "core/events/ThreadLocalEventNames.h"
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +010065#include "core/fetch/ResourceFetcher.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010066#include "core/html/HTMLImageElement.h"
Torne (Richard Coles)f5e4ad52013-08-05 13:57:57 +010067#include "core/html/HTMLInputElement.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010068#include "core/html/HTMLTextAreaElement.h"
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +010069#include "core/loader/EmptyClients.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010070#include "core/page/EditorClient.h"
71#include "core/page/EventHandler.h"
72#include "core/page/FocusController.h"
Torne (Richard Coles)1e202182013-10-18 15:46:42 +010073#include "core/frame/Frame.h"
74#include "core/frame/FrameView.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010075#include "core/page/Page.h"
76#include "core/page/Settings.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010077#include "core/platform/Pasteboard.h"
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +010078#include "core/platform/chromium/ChromiumDataObject.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010079#include "core/rendering/HitTestResult.h"
Torne (Richard Coles)51b29062013-11-28 11:56:03 +000080#include "platform/KillRing.h"
Ben Murdoch591b9582013-07-10 11:41:44 +010081#include "wtf/unicode/CharacterNames.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010082
83namespace WebCore {
84
85using namespace std;
86using namespace HTMLNames;
87using namespace WTF;
88using namespace Unicode;
89
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +010090Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor)
91 : m_editor(editor)
92{
93 ++m_editor->m_preventRevealSelection;
94}
95
96Editor::RevealSelectionScope::~RevealSelectionScope()
97{
98 ASSERT(m_editor->m_preventRevealSelection);
99 --m_editor->m_preventRevealSelection;
100 if (!m_editor->m_preventRevealSelection)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100101 m_editor->m_frame.selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +0100102}
103
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100104// When an event handler has moved the selection outside of a text control
105// we should use the target control's selection for this editing operation.
106VisibleSelection Editor::selectionForCommand(Event* event)
107{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100108 VisibleSelection selection = m_frame.selection().selection();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100109 if (!event)
110 return selection;
111 // If the target is a text control, and the current selection is outside of its shadow tree,
112 // then use the saved selection for that text control.
113 HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
114 HTMLTextFormControlElement* textFromControlOfTarget = isHTMLTextFormControlElement(event->target()->toNode()) ? toHTMLTextFormControlElement(event->target()->toNode()) : 0;
115 if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
116 if (RefPtr<Range> range = textFromControlOfTarget->selection())
117 return VisibleSelection(range.get(), DOWNSTREAM, selection.isDirectional());
118 }
119 return selection;
120}
121
122// Function considers Mac editing behavior a fallback when Page or Settings is not available.
123EditingBehavior Editor::behavior() const
124{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100125 if (!m_frame.settings())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100126 return EditingBehavior(EditingMacBehavior);
127
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100128 return EditingBehavior(m_frame.settings()->editingBehaviorType());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100129}
130
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100131static EditorClient& emptyEditorClient()
132{
133 DEFINE_STATIC_LOCAL(EmptyEditorClient, client, ());
134 return client;
135}
136
137EditorClient& Editor::client() const
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100138{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100139 if (Page* page = m_frame.page())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100140 return page->editorClient();
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100141 return emptyEditorClient();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100142}
143
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000144UndoStack* Editor::undoStack() const
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100145{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000146 if (Page* page = m_frame.page())
147 return &page->undoStack();
148 return 0;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100149}
150
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100151bool Editor::handleTextEvent(TextEvent* event)
152{
153 // Default event handling for Drag and Drop will be handled by DragController
154 // so we leave the event for it.
155 if (event->isDrop())
156 return false;
157
158 if (event->isPaste()) {
159 if (event->pastingFragment())
160 replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
Ben Murdoch02772c62013-07-26 10:21:05 +0100161 else
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100162 replaceSelectionWithText(event->data(), false, event->shouldSmartReplace());
163 return true;
164 }
165
166 String data = event->data();
167 if (data == "\n") {
168 if (event->isLineBreak())
169 return insertLineBreak();
170 return insertParagraphSeparator();
171 }
172
173 return insertTextWithoutSendingTextEvent(data, false, event);
174}
175
176bool Editor::canEdit() const
177{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100178 return m_frame.selection().rootEditableElement();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100179}
180
181bool Editor::canEditRichly() const
182{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100183 return m_frame.selection().isContentRichlyEditable();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100184}
185
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100186// WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items. They
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100187// also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
188// We need to use onbeforecopy as a real menu enabler because we allow elements that are not
189// normally selectable to implement copy/paste (like divs, or a document body).
190
191bool Editor::canDHTMLCut()
192{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100193 return !m_frame.selection().isInPasswordField() && !dispatchCPPEvent(EventTypeNames::beforecut, ClipboardNumb);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100194}
195
196bool Editor::canDHTMLCopy()
197{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100198 return !m_frame.selection().isInPasswordField() && !dispatchCPPEvent(EventTypeNames::beforecopy, ClipboardNumb);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100199}
200
201bool Editor::canDHTMLPaste()
202{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100203 return !dispatchCPPEvent(EventTypeNames::beforepaste, ClipboardNumb);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100204}
205
206bool Editor::canCut() const
207{
208 return canCopy() && canDelete();
209}
210
211static HTMLImageElement* imageElementFromImageDocument(Document* document)
212{
213 if (!document)
214 return 0;
215 if (!document->isImageDocument())
216 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100217
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100218 HTMLElement* body = document->body();
219 if (!body)
220 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100221
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100222 Node* node = body->firstChild();
223 if (!node)
Ben Murdoch02772c62013-07-26 10:21:05 +0100224 return 0;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100225 if (!node->hasTagName(imgTag))
226 return 0;
Torne (Richard Coles)521d96e2013-06-19 11:58:24 +0100227 return toHTMLImageElement(node);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100228}
229
230bool Editor::canCopy() const
231{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100232 if (imageElementFromImageDocument(m_frame.document()))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100233 return true;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100234 FrameSelection& selection = m_frame.selection();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100235 return selection.isRange() && !selection.isInPasswordField();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100236}
237
238bool Editor::canPaste() const
239{
240 return canEdit();
241}
242
243bool Editor::canDelete() const
244{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100245 FrameSelection& selection = m_frame.selection();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100246 return selection.isRange() && selection.rootEditableElement();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100247}
248
249bool Editor::canDeleteRange(Range* range) const
250{
251 Node* startContainer = range->startContainer();
252 Node* endContainer = range->endContainer();
253 if (!startContainer || !endContainer)
254 return false;
Ben Murdoch02772c62013-07-26 10:21:05 +0100255
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100256 if (!startContainer->rendererIsEditable() || !endContainer->rendererIsEditable())
257 return false;
258
Ben Murdoch1fad5ca2013-08-07 11:05:11 +0100259 if (range->collapsed(IGNORE_EXCEPTION)) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100260 VisiblePosition start(range->startPosition(), DOWNSTREAM);
261 VisiblePosition previous = start.previous();
262 // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
263 if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer->rootEditableElement())
264 return false;
265 }
266 return true;
267}
268
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000269bool Editor::smartInsertDeleteEnabled() const
Ben Murdoch02772c62013-07-26 10:21:05 +0100270{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000271 if (Settings* settings = m_frame.settings())
272 return settings->smartInsertDeleteEnabled();
273 return false;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100274}
Ben Murdoch02772c62013-07-26 10:21:05 +0100275
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000276bool Editor::canSmartCopyOrDelete() const
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100277{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000278 return smartInsertDeleteEnabled() && m_frame.selection().granularity() == WordGranularity;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100279}
280
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000281bool Editor::isSelectTrailingWhitespaceEnabled() const
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100282{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000283 if (Settings* settings = m_frame.settings())
284 return settings->selectTrailingWhitespaceEnabled();
285 return false;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100286}
287
288bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool killRing, bool isTypingAction)
289{
290 if (!canEdit())
291 return false;
292
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100293 if (m_frame.selection().isRange()) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100294 if (isTypingAction) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100295 ASSERT(m_frame.document());
296 TypingCommand::deleteKeyPressed(*m_frame.document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100297 revealSelectionAfterEditingOperation();
298 } else {
299 if (killRing)
300 addToKillRing(selectedRange().get(), false);
301 deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
302 // Implicitly calls revealSelectionAfterEditingOperation().
303 }
304 } else {
305 TypingCommand::Options options = 0;
306 if (canSmartCopyOrDelete())
307 options |= TypingCommand::SmartDelete;
308 if (killRing)
309 options |= TypingCommand::KillRing;
310 switch (direction) {
311 case DirectionForward:
312 case DirectionRight:
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100313 ASSERT(m_frame.document());
314 TypingCommand::forwardDeleteKeyPressed(*m_frame.document(), options, granularity);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100315 break;
316 case DirectionBackward:
317 case DirectionLeft:
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100318 ASSERT(m_frame.document());
319 TypingCommand::deleteKeyPressed(*m_frame.document(), options, granularity);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100320 break;
321 }
322 revealSelectionAfterEditingOperation();
323 }
324
325 // FIXME: We should to move this down into deleteKeyPressed.
326 // clear the "start new kill ring sequence" setting, because it was set to true
327 // when the selection was updated by deleting the range
328 if (killRing)
329 setStartNewKillRingSequence(false);
330
331 return true;
332}
333
334void Editor::deleteSelectionWithSmartDelete(bool smartDelete)
335{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100336 if (m_frame.selection().isNone())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100337 return;
Ben Murdoch02772c62013-07-26 10:21:05 +0100338
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100339 ASSERT(m_frame.document());
340 DeleteSelectionCommand::create(*m_frame.document(), smartDelete)->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100341}
342
343void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
344{
345 Node* target = findEventTargetFromSelection();
346 if (!target)
347 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100348 target->dispatchEvent(TextEvent::createForPlainTextPaste(m_frame.domWindow(), pastingText, smartReplace), IGNORE_EXCEPTION);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100349}
350
351void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
352{
353 Node* target = findEventTargetFromSelection();
354 if (!target)
355 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100356 target->dispatchEvent(TextEvent::createForFragmentPaste(m_frame.domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100357}
358
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100359bool Editor::tryDHTMLCopy()
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100360{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100361 if (m_frame.selection().isInPasswordField())
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100362 return false;
363
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100364 return !dispatchCPPEvent(EventTypeNames::copy, ClipboardWritable);
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100365}
366
367bool Editor::tryDHTMLCut()
368{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100369 if (m_frame.selection().isInPasswordField())
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100370 return false;
371
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100372 return !dispatchCPPEvent(EventTypeNames::cut, ClipboardWritable);
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100373}
374
375bool Editor::tryDHTMLPaste(PasteMode pasteMode)
376{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100377 return !dispatchCPPEvent(EventTypeNames::paste, ClipboardReadable, pasteMode);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100378}
379
380void Editor::pasteAsPlainTextWithPasteboard(Pasteboard* pasteboard)
381{
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100382 String text = pasteboard->plainText();
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100383 pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100384}
385
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100386void Editor::pasteWithPasteboard(Pasteboard* pasteboard)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100387{
388 RefPtr<Range> range = selectedRange();
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100389 RefPtr<DocumentFragment> fragment;
390 bool chosePlainText = false;
391
392 if (pasteboard->isHTMLAvailable()) {
393 unsigned fragmentStart = 0;
394 unsigned fragmentEnd = 0;
395 KURL url;
396 String markup = pasteboard->readHTML(url, fragmentStart, fragmentEnd);
397 if (!markup.isEmpty()) {
398 ASSERT(m_frame.document());
399 fragment = createFragmentFromMarkupWithContext(*m_frame.document(), markup, fragmentStart, fragmentEnd, url, DisallowScriptingAndPluginContent);
400 }
401 }
402
403 if (!fragment) {
404 String text = pasteboard->plainText();
405 if (!text.isEmpty()) {
406 chosePlainText = true;
407 fragment = createFragmentFromText(range.get(), text);
408 }
409 }
410
411 if (fragment)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100412 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), chosePlainText);
413}
414
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000415void Editor::writeSelectionToPasteboard(Pasteboard* pasteboard, Range* selectedRange, const String& plainText)
416{
417 String html = createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
418 KURL url = selectedRange->startContainer()->document().url();
419 pasteboard->writeHTML(html, url, plainText, canSmartCopyOrDelete());
420}
421
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100422// Returns whether caller should continue with "the default processing", which is the same as
423// the event handler NOT setting the return value to false
424bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPolicy policy, PasteMode pasteMode)
425{
426 Node* target = findEventTargetFromSelection();
427 if (!target)
428 return true;
429
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100430 RefPtr<Clipboard> clipboard = Clipboard::create(
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100431 Clipboard::CopyAndPaste,
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100432 policy,
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100433 policy == ClipboardWritable
434 ? ChromiumDataObject::create()
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100435 : ChromiumDataObject::createFromPasteboard(pasteMode));
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100436
437 RefPtr<Event> evt = ClipboardEvent::create(eventType, true, true, clipboard);
438 target->dispatchEvent(evt, IGNORE_EXCEPTION);
439 bool noDefaultProcessing = evt->defaultPrevented();
440 if (noDefaultProcessing && policy == ClipboardWritable) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100441 RefPtr<ChromiumDataObject> dataObject = clipboard->dataObject();
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100442 Pasteboard::generalPasteboard()->writeDataObject(dataObject.release());
443 }
444
445 // invalidate clipboard here for security
446 clipboard->setAccessPolicy(ClipboardNumb);
447
448 return !noDefaultProcessing;
449}
450
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100451bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard)
452{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000453 return smartInsertDeleteEnabled() && pasteboard->canSmartReplace();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100454}
455
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100456void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
457{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100458 if (m_frame.selection().isNone() || !m_frame.selection().isContentEditable() || !fragment)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100459 return;
460
461 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
462 if (selectReplacement)
463 options |= ReplaceSelectionCommand::SelectReplacement;
464 if (smartReplace)
465 options |= ReplaceSelectionCommand::SmartReplace;
466 if (matchStyle)
467 options |= ReplaceSelectionCommand::MatchStyle;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100468 ASSERT(m_frame.document());
469 ReplaceSelectionCommand::create(*m_frame.document(), fragment, options, EditActionPaste)->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100470 revealSelectionAfterEditingOperation();
471
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000472 if (m_frame.selection().isInPasswordField() || !spellChecker().isContinuousSpellCheckingEnabled())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100473 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100474 spellChecker().chunkAndMarkAllMisspellingsAndBadGrammar(m_frame.selection().rootEditableElement());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100475}
476
477void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace)
478{
Ben Murdoch02772c62013-07-26 10:21:05 +0100479 replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), text), selectReplacement, smartReplace, true);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100480}
481
482PassRefPtr<Range> Editor::selectedRange()
483{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100484 return m_frame.selection().toNormalizedRange();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100485}
486
487bool Editor::shouldDeleteRange(Range* range) const
488{
Ben Murdoch1fad5ca2013-08-07 11:05:11 +0100489 if (!range || range->collapsed(IGNORE_EXCEPTION))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100490 return false;
Ben Murdoch02772c62013-07-26 10:21:05 +0100491
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100492 return canDeleteRange(range);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100493}
494
495void Editor::notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
496{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000497 client().respondToChangedSelection(m_frame.selection().selectionType());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100498 setStartNewKillRingSequence(true);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100499}
500
501void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
502{
503 if (AXObjectCache::accessibilityEnabled()) {
504 Node* node = endingSelection.start().deprecatedNode();
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100505 if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100506 cache->postNotification(node, AXObjectCache::AXValueChanged, false);
507 }
508
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100509 spellChecker().updateMarkersForWordsAffectedByEditing(true);
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100510 client().respondToChangedContents();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100511}
512
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100513TriState Editor::selectionUnorderedListState() const
514{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100515 if (m_frame.selection().isCaret()) {
516 if (enclosingNodeWithTag(m_frame.selection().selection().start(), ulTag))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100517 return TrueTriState;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100518 } else if (m_frame.selection().isRange()) {
519 Node* startNode = enclosingNodeWithTag(m_frame.selection().selection().start(), ulTag);
520 Node* endNode = enclosingNodeWithTag(m_frame.selection().selection().end(), ulTag);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100521 if (startNode && endNode && startNode == endNode)
522 return TrueTriState;
523 }
524
525 return FalseTriState;
526}
527
528TriState Editor::selectionOrderedListState() const
529{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100530 if (m_frame.selection().isCaret()) {
531 if (enclosingNodeWithTag(m_frame.selection().selection().start(), olTag))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100532 return TrueTriState;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100533 } else if (m_frame.selection().isRange()) {
534 Node* startNode = enclosingNodeWithTag(m_frame.selection().selection().start(), olTag);
535 Node* endNode = enclosingNodeWithTag(m_frame.selection().selection().end(), olTag);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100536 if (startNode && endNode && startNode == endNode)
537 return TrueTriState;
538 }
539
540 return FalseTriState;
541}
542
543PassRefPtr<Node> Editor::insertOrderedList()
544{
545 if (!canEditRichly())
546 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100547
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100548 ASSERT(m_frame.document());
549 RefPtr<Node> newList = InsertListCommand::insertList(*m_frame.document(), InsertListCommand::OrderedList);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100550 revealSelectionAfterEditingOperation();
551 return newList;
552}
553
554PassRefPtr<Node> Editor::insertUnorderedList()
555{
556 if (!canEditRichly())
557 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100558
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100559 ASSERT(m_frame.document());
560 RefPtr<Node> newList = InsertListCommand::insertList(*m_frame.document(), InsertListCommand::UnorderedList);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100561 revealSelectionAfterEditingOperation();
562 return newList;
563}
564
565bool Editor::canIncreaseSelectionListLevel()
566{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100567 ASSERT(m_frame.document());
568 return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100569}
570
571bool Editor::canDecreaseSelectionListLevel()
572{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100573 ASSERT(m_frame.document());
574 return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100575}
576
577PassRefPtr<Node> Editor::increaseSelectionListLevel()
578{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100579 if (!canEditRichly() || m_frame.selection().isNone())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100580 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100581
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100582 ASSERT(m_frame.document());
583 RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100584 revealSelectionAfterEditingOperation();
585 return newList;
586}
587
588PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered()
589{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100590 if (!canEditRichly() || m_frame.selection().isNone())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100591 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100592
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100593 ASSERT(m_frame.document());
594 RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100595 revealSelectionAfterEditingOperation();
596 return newList.release();
597}
598
599PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
600{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100601 if (!canEditRichly() || m_frame.selection().isNone())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100602 return 0;
Ben Murdoch02772c62013-07-26 10:21:05 +0100603
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100604 ASSERT(m_frame.document());
605 RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100606 revealSelectionAfterEditingOperation();
607 return newList.release();
608}
609
610void Editor::decreaseSelectionListLevel()
611{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100612 if (!canEditRichly() || m_frame.selection().isNone())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100613 return;
Ben Murdoch02772c62013-07-26 10:21:05 +0100614
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100615 ASSERT(m_frame.document());
616 DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(*m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100617 revealSelectionAfterEditingOperation();
618}
619
620void Editor::removeFormattingAndStyle()
621{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100622 ASSERT(m_frame.document());
623 RemoveFormatCommand::create(*m_frame.document())->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100624}
625
Ben Murdoch02772c62013-07-26 10:21:05 +0100626void Editor::clearLastEditCommand()
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100627{
628 m_lastEditCommand.clear();
629}
630
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100631Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const
632{
633 Node* target = selection.start().element();
634 if (!target)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100635 target = m_frame.document()->body();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100636
637 return target;
638}
639
640Node* Editor::findEventTargetFromSelection() const
641{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100642 return findEventTargetFrom(m_frame.selection().selection());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100643}
644
645void Editor::applyStyle(StylePropertySet* style, EditAction editingAction)
646{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100647 switch (m_frame.selection().selectionType()) {
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000648 case NoSelection:
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100649 // do nothing
650 break;
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000651 case CaretSelection:
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100652 computeAndSetTypingStyle(style, editingAction);
653 break;
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000654 case RangeSelection:
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100655 if (style) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100656 ASSERT(m_frame.document());
657 ApplyStyleCommand::create(*m_frame.document(), EditingStyle::create(style).get(), editingAction)->apply();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100658 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100659 break;
660 }
661}
Ben Murdoch02772c62013-07-26 10:21:05 +0100662
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100663void Editor::applyParagraphStyle(StylePropertySet* style, EditAction editingAction)
664{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000665 if (m_frame.selection().isNone() || !style)
666 return;
667 ASSERT(m_frame.document());
668 ApplyStyleCommand::create(*m_frame.document(), EditingStyle::create(style).get(), editingAction, ApplyStyleCommand::ForceBlockProperties)->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100669}
670
671void Editor::applyStyleToSelection(StylePropertySet* style, EditAction editingAction)
672{
673 if (!style || style->isEmpty() || !canEditRichly())
674 return;
675
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100676 applyStyle(style, editingAction);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100677}
678
679void Editor::applyParagraphStyleToSelection(StylePropertySet* style, EditAction editingAction)
680{
681 if (!style || style->isEmpty() || !canEditRichly())
682 return;
Ben Murdoch02772c62013-07-26 10:21:05 +0100683
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100684 applyParagraphStyle(style, editingAction);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100685}
686
687bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
688{
689 return EditingStyle::create(propertyID, value)->triStateOfStyle(
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100690 EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor).get());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100691}
692
693TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
694{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100695 return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100696}
697
698String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
699{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100700 RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100701 propertyID == CSSPropertyBackgroundColor);
702 if (!selectionStyle || !selectionStyle->style())
703 return String();
704
705 if (propertyID == CSSPropertyFontSize)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100706 return String::number(selectionStyle->legacyFontSize(m_frame.document()));
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100707 return selectionStyle->style()->getPropertyValue(propertyID);
708}
709
710void Editor::indent()
711{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100712 ASSERT(m_frame.document());
713 IndentOutdentCommand::create(*m_frame.document(), IndentOutdentCommand::Indent)->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100714}
715
716void Editor::outdent()
717{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100718 ASSERT(m_frame.document());
719 IndentOutdentCommand::create(*m_frame.document(), IndentOutdentCommand::Outdent)->apply();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100720}
721
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +0100722static void dispatchEditableContentChangedEvents(PassRefPtr<Element> startRoot, PassRefPtr<Element> endRoot)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100723{
724 if (startRoot)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100725 startRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableContentChanged), IGNORE_EXCEPTION);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100726 if (endRoot && endRoot != startRoot)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100727 endRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableContentChanged), IGNORE_EXCEPTION);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100728}
729
730void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
731{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100732 EventQueueScope scope;
733 m_frame.document()->updateLayout();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100734
735 EditCommandComposition* composition = cmd->composition();
736 ASSERT(composition);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100737 dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100738 VisibleSelection newSelection(cmd->endingSelection());
739
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100740 // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
Torne (Richard Coles)81a51572013-05-13 16:52:28 +0100741 changeSelectionAfterCommand(newSelection, 0);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100742
743 if (!cmd->preservesTypingStyle())
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100744 m_frame.selection().clearTypingStyle();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100745
746 // Command will be equal to last edit command only in the case of typing
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100747 if (m_lastEditCommand.get() == cmd) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100748 ASSERT(cmd->isTypingCommand());
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100749 } else {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100750 // Only register a new undo command if the command passed in is
751 // different from the last command
752 m_lastEditCommand = cmd;
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000753 if (UndoStack* undoStack = this->undoStack())
754 undoStack->registerUndoStep(m_lastEditCommand->ensureComposition());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100755 }
756
757 respondToChangedContents(newSelection);
758}
759
760void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd)
761{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100762 EventQueueScope scope;
763 m_frame.document()->updateLayout();
764
765 dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
Torne (Richard Coles)521d96e2013-06-19 11:58:24 +0100766
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100767 VisibleSelection newSelection(cmd->startingSelection());
768 changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
Torne (Richard Coles)521d96e2013-06-19 11:58:24 +0100769
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100770 m_lastEditCommand = 0;
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000771 if (UndoStack* undoStack = this->undoStack())
772 undoStack->registerRedoStep(cmd);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100773 respondToChangedContents(newSelection);
774}
775
776void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd)
777{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100778 EventQueueScope scope;
779 m_frame.document()->updateLayout();
780
781 dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
Torne (Richard Coles)521d96e2013-06-19 11:58:24 +0100782
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100783 VisibleSelection newSelection(cmd->endingSelection());
784 changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
Torne (Richard Coles)521d96e2013-06-19 11:58:24 +0100785
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100786 m_lastEditCommand = 0;
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000787 if (UndoStack* undoStack = this->undoStack())
788 undoStack->registerUndoStep(cmd);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100789 respondToChangedContents(newSelection);
790}
791
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100792PassOwnPtr<Editor> Editor::create(Frame& frame)
793{
794 return adoptPtr(new Editor(frame));
795}
796
Torne (Richard Coles)c0e19a62013-08-30 15:15:11 +0100797Editor::Editor(Frame& frame)
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100798 : m_frame(frame)
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +0100799 , m_preventRevealSelection(0)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100800 , m_shouldStartNewKillRingSequence(false)
801 // This is off by default, since most editors want this behavior (this matches IE but not FF).
802 , m_shouldStyleWithCSS(false)
803 , m_killRing(adoptPtr(new KillRing))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100804 , m_areMarkedTextMatchesHighlighted(false)
805 , m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv)
806 , m_overwriteModeEnabled(false)
807{
808}
809
810Editor::~Editor()
811{
812}
813
814void Editor::clear()
815{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100816 m_frame.inputMethodController().clear();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100817 m_shouldStyleWithCSS = false;
818 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
819}
820
821bool Editor::insertText(const String& text, Event* triggeringEvent)
822{
Torne (Richard Coles)f79f16f2013-10-31 11:16:44 +0000823 return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100824}
825
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100826bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
827{
828 if (text.isEmpty())
829 return false;
830
831 VisibleSelection selection = selectionForCommand(triggeringEvent);
832 if (!selection.isContentEditable())
833 return false;
834 RefPtr<Range> range = selection.toNormalizedRange();
835
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000836 spellChecker().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100837
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100838 // Get the selection to use for the event that triggered this insertText.
839 // If the event handler changed the selection, we may want to use a different selection
840 // that is contained in the event target.
841 selection = selectionForCommand(triggeringEvent);
842 if (selection.isContentEditable()) {
843 if (Node* selectionStart = selection.start().deprecatedNode()) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100844 RefPtr<Document> document(selectionStart->document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100845
846 // Insert the text
Torne (Richard Coles)81a51572013-05-13 16:52:28 +0100847 TypingCommand::Options options = 0;
848 if (selectInsertedText)
849 options |= TypingCommand::SelectInsertedText;
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100850 TypingCommand::insertText(*document.get(), text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100851
852 // Reveal the current selection
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +0100853 if (Frame* editedFrame = document->frame()) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100854 if (Page* page = editedFrame->page())
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100855 page->focusController().focusedOrMainFrame()->selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +0100856 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100857 }
858 }
859
860 return true;
861}
862
863bool Editor::insertLineBreak()
864{
865 if (!canEdit())
866 return false;
867
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100868 VisiblePosition caret = m_frame.selection().selection().visibleStart();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100869 bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100870 ASSERT(m_frame.document());
871 TypingCommand::insertLineBreak(*m_frame.document(), 0);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100872 revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
873
874 return true;
875}
876
877bool Editor::insertParagraphSeparator()
878{
879 if (!canEdit())
880 return false;
881
882 if (!canEditRichly())
883 return insertLineBreak();
884
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100885 VisiblePosition caret = m_frame.selection().selection().visibleStart();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100886 bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100887 ASSERT(m_frame.document());
888 TypingCommand::insertParagraphSeparator(*m_frame.document(), 0);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100889 revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
890
891 return true;
892}
893
894void Editor::cut()
895{
896 if (tryDHTMLCut())
897 return; // DHTML did the whole operation
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100898 if (!canCut())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100899 return;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100900 RefPtr<Range> selection = selectedRange();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100901 if (shouldDeleteRange(selection.get())) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100902 spellChecker().updateMarkersForWordsAffectedByEditing(true);
903 String plainText = m_frame.selectedTextForClipboard();
904 if (enclosingTextFormControl(m_frame.selection().start())) {
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100905 Pasteboard::generalPasteboard()->writePlainText(plainText,
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100906 canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100907 } else {
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000908 writeSelectionToPasteboard(Pasteboard::generalPasteboard(), selection.get(), plainText);
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +0100909 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100910 deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
911 }
912}
913
914void Editor::copy()
915{
916 if (tryDHTMLCopy())
917 return; // DHTML did the whole operation
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100918 if (!canCopy())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100919 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100920 if (enclosingTextFormControl(m_frame.selection().start())) {
921 Pasteboard::generalPasteboard()->writePlainText(m_frame.selectedTextForClipboard(),
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100922 canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
923 } else {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100924 Document* document = m_frame.document();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100925 if (HTMLImageElement* imageElement = imageElementFromImageDocument(document))
926 Pasteboard::generalPasteboard()->writeImage(imageElement, document->url(), document->title());
927 else
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000928 writeSelectionToPasteboard(Pasteboard::generalPasteboard(), selectedRange().get(), m_frame.selectedTextForClipboard());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100929 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100930}
931
932void Editor::paste()
933{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100934 ASSERT(m_frame.document());
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100935 if (tryDHTMLPaste(AllMimeTypes))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100936 return; // DHTML did the whole operation
937 if (!canPaste())
938 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100939 spellChecker().updateMarkersForWordsAffectedByEditing(false);
940 ResourceFetcher* loader = m_frame.document()->fetcher();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100941 ResourceCacheValidationSuppressor validationSuppressor(loader);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100942 if (m_frame.selection().isContentRichlyEditable())
943 pasteWithPasteboard(Pasteboard::generalPasteboard());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100944 else
945 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
946}
947
948void Editor::pasteAsPlainText()
949{
Torne (Richard Coles)06f816c2013-09-26 13:25:12 +0100950 if (tryDHTMLPaste(PlainTextOnly))
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100951 return;
952 if (!canPaste())
953 return;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100954 spellChecker().updateMarkersForWordsAffectedByEditing(false);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100955 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
956}
957
958void Editor::performDelete()
959{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +0100960 if (!canDelete())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100961 return;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100962 addToKillRing(selectedRange().get(), false);
963 deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
964
965 // clear the "start new kill ring sequence" setting, because it was set to true
966 // when the selection was updated by deleting the range
967 setStartNewKillRingSequence(false);
968}
969
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100970void Editor::copyImage(const HitTestResult& result)
971{
972 KURL url = result.absoluteLinkURL();
973 if (url.isEmpty())
974 url = result.absoluteImageURL();
975
976 Pasteboard::generalPasteboard()->writeImage(result.innerNonSharedNode(), url, result.altDisplayString());
977}
978
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100979void Editor::clearUndoRedoOperations()
980{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000981 if (UndoStack* undoStack = this->undoStack())
982 undoStack->clearUndoRedoOperations();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100983}
984
985bool Editor::canUndo()
986{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000987 if (UndoStack* undoStack = this->undoStack())
988 return undoStack->canUndo();
989 return false;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100990}
991
992void Editor::undo()
993{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000994 if (UndoStack* undoStack = this->undoStack())
995 undoStack->undo();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100996}
997
998bool Editor::canRedo()
999{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001000 if (UndoStack* undoStack = this->undoStack())
1001 return undoStack->canRedo();
1002 return false;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001003}
1004
1005void Editor::redo()
1006{
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001007 if (UndoStack* undoStack = this->undoStack())
1008 undoStack->redo();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001009}
1010
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001011void Editor::setBaseWritingDirection(WritingDirection direction)
1012{
Torne (Richard Coles)c0e19a62013-08-30 15:15:11 +01001013 Node* focusedElement = frame().document()->focusedElement();
Ben Murdoch7757ec22013-07-23 11:17:36 +01001014 if (focusedElement && isHTMLTextFormControlElement(focusedElement)) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001015 if (direction == NaturalWritingDirection)
1016 return;
Ben Murdoch7757ec22013-07-23 11:17:36 +01001017 toHTMLElement(focusedElement)->setAttribute(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
1018 focusedElement->dispatchInputEvent();
Torne (Richard Coles)c0e19a62013-08-30 15:15:11 +01001019 frame().document()->updateStyleIfNeeded();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001020 return;
1021 }
1022
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +01001023 RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001024 style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
1025 applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
1026}
1027
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001028void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
1029{
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +01001030 if (m_preventRevealSelection)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001031 return;
1032
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001033 m_frame.selection().revealSelection(alignment, revealExtentOption);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001034}
1035
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001036void Editor::transpose()
1037{
1038 if (!canEdit())
1039 return;
1040
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001041 VisibleSelection selection = m_frame.selection().selection();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +01001042 if (!selection.isCaret())
1043 return;
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001044
1045 // Make a selection that goes back one character and forward two characters.
1046 VisiblePosition caret = selection.visibleStart();
1047 VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
1048 VisiblePosition previous = next.previous();
1049 if (next == previous)
1050 return;
1051 previous = previous.previous();
1052 if (!inSameParagraph(next, previous))
1053 return;
1054 RefPtr<Range> range = makeRange(previous, next);
1055 if (!range)
1056 return;
1057 VisibleSelection newSelection(range.get(), DOWNSTREAM);
1058
1059 // Transpose the two characters.
1060 String text = plainText(range.get());
1061 if (text.length() != 2)
1062 return;
1063 String transposed = text.right(1) + text.left(1);
1064
1065 // Select the two characters.
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001066 if (newSelection != m_frame.selection().selection())
1067 m_frame.selection().setSelection(newSelection);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001068
1069 // Insert the transposed characters.
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001070 replaceSelectionWithText(transposed, false, false);
1071}
1072
1073void Editor::addToKillRing(Range* range, bool prepend)
1074{
1075 if (m_shouldStartNewKillRingSequence)
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001076 killRing().startNewSequence();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001077
1078 String text = plainText(range);
1079 if (prepend)
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001080 killRing().prepend(text);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001081 else
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001082 killRing().append(text);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001083 m_shouldStartNewKillRingSequence = false;
1084}
1085
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001086void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions options)
1087{
1088 // If the new selection is orphaned, then don't update the selection.
1089 if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
1090 return;
1091
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001092 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001093 bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
1094 m_frame.selection().setSelection(newSelection, options);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001095
1096 // Some editing operations change the selection visually without affecting its position within the DOM.
1097 // For example when you press return in the following (the caret is marked by ^):
1098 // <div contentEditable="true"><div>^Hello</div></div>
1099 // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
1100 // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
1101 // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
1102 // starts a new kill ring sequence, but we want to do these things (matches AppKit).
Torne (Richard Coles)e1f1df52013-08-23 16:39:30 +01001103 if (selectionDidNotChangeDOMPosition)
Torne (Richard Coles)51b29062013-11-28 11:56:03 +00001104 client().respondToChangedSelection(m_frame.selection().selectionType());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001105}
1106
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001107IntRect Editor::firstRectForRange(Range* range) const
1108{
1109 LayoutUnit extraWidthToEndOfLine = 0;
1110 ASSERT(range->startContainer());
1111 ASSERT(range->endContainer());
1112
1113 IntRect startCaretRect = RenderedPosition(VisiblePosition(range->startPosition()).deepEquivalent(), DOWNSTREAM).absoluteRect(&extraWidthToEndOfLine);
1114 if (startCaretRect == LayoutRect())
1115 return IntRect();
1116
1117 IntRect endCaretRect = RenderedPosition(VisiblePosition(range->endPosition()).deepEquivalent(), UPSTREAM).absoluteRect();
1118 if (endCaretRect == LayoutRect())
1119 return IntRect();
1120
1121 if (startCaretRect.y() == endCaretRect.y()) {
1122 // start and end are on the same line
1123 return IntRect(min(startCaretRect.x(), endCaretRect.x()),
1124 startCaretRect.y(),
1125 abs(endCaretRect.x() - startCaretRect.x()),
1126 max(startCaretRect.height(), endCaretRect.height()));
1127 }
1128
1129 // start and end aren't on the same line, so go from start to the end of its line
1130 return IntRect(startCaretRect.x(),
1131 startCaretRect.y(),
1132 startCaretRect.width() + extraWidthToEndOfLine,
1133 startCaretRect.height());
1134}
1135
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001136void Editor::computeAndSetTypingStyle(StylePropertySet* style, EditAction editingAction)
1137{
1138 if (!style || style->isEmpty()) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001139 m_frame.selection().clearTypingStyle();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001140 return;
1141 }
1142
1143 // Calculate the current typing style.
1144 RefPtr<EditingStyle> typingStyle;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001145 if (m_frame.selection().typingStyle()) {
1146 typingStyle = m_frame.selection().typingStyle()->copy();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001147 typingStyle->overrideWithStyle(style);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001148 } else {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001149 typingStyle = EditingStyle::create(style);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001150 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001151
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001152 typingStyle->prepareToApplyAt(m_frame.selection().selection().visibleStart().deepEquivalent(), EditingStyle::PreserveWritingDirection);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001153
1154 // Handle block styles, substracting these from the typing style.
1155 RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +01001156 if (!blockStyle->isEmpty()) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001157 ASSERT(m_frame.document());
1158 ApplyStyleCommand::create(*m_frame.document(), blockStyle.get(), editingAction)->apply();
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +01001159 }
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001160
1161 // Set the remaining style as the typing style.
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001162 m_frame.selection().setTypingStyle(typingStyle);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001163}
1164
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001165bool Editor::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
1166{
1167 FindOptions options = (forward ? 0 : Backwards) | (caseFlag ? 0 : CaseInsensitive) | (wrapFlag ? WrapAround : 0) | (startInSelection ? StartInSelection : 0);
1168 return findString(target, options);
1169}
1170
1171bool Editor::findString(const String& target, FindOptions options)
1172{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001173 VisibleSelection selection = m_frame.selection().selection();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001174
1175 RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
1176
1177 if (!resultRange)
1178 return false;
1179
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001180 m_frame.selection().setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM));
1181 m_frame.selection().revealSelection();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001182 return true;
1183}
1184
1185PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
1186{
1187 RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
1188 if (!nextMatch)
1189 return 0;
1190
1191 nextMatch->firstNode()->renderer()->scrollRectToVisible(nextMatch->boundingBox(),
1192 ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
1193
1194 return nextMatch.release();
1195}
1196
1197PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
1198{
1199 if (target.isEmpty())
1200 return 0;
1201
1202 // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
1203 // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001204 RefPtr<Range> searchRange(rangeOfContents(m_frame.document()));
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001205
1206 bool forward = !(options & Backwards);
1207 bool startInReferenceRange = referenceRange && (options & StartInSelection);
1208 if (referenceRange) {
1209 if (forward)
1210 searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
1211 else
1212 searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
1213 }
1214
1215 RefPtr<Node> shadowTreeRoot = referenceRange && referenceRange->startContainer() ? referenceRange->startContainer()->nonBoundaryShadowTreeRootNode() : 0;
1216 if (shadowTreeRoot) {
1217 if (forward)
1218 searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
1219 else
1220 searchRange->setStart(shadowTreeRoot.get(), 0);
1221 }
1222
1223 RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, options));
1224 // If we started in the reference range and the found range exactly matches the reference range, find again.
1225 // Build a selection with the found range to remove collapsed whitespace.
1226 // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1227 if (startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001228 searchRange = rangeOfContents(m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001229 if (forward)
1230 searchRange->setStart(referenceRange->endPosition());
1231 else
1232 searchRange->setEnd(referenceRange->startPosition());
1233
1234 if (shadowTreeRoot) {
1235 if (forward)
1236 searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
1237 else
1238 searchRange->setStart(shadowTreeRoot.get(), 0);
1239 }
1240
1241 resultRange = findPlainText(searchRange.get(), target, options);
1242 }
1243
1244 // If nothing was found in the shadow tree, search in main content following the shadow tree.
Ben Murdoch1fad5ca2013-08-07 11:05:11 +01001245 if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && shadowTreeRoot) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001246 searchRange = rangeOfContents(m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001247 if (forward)
1248 searchRange->setStartAfter(shadowTreeRoot->shadowHost());
1249 else
1250 searchRange->setEndBefore(shadowTreeRoot->shadowHost());
1251
1252 resultRange = findPlainText(searchRange.get(), target, options);
1253 }
1254
1255 // If we didn't find anything and we're wrapping, search again in the entire document (this will
1256 // redundantly re-search the area already searched in some cases).
Ben Murdoch1fad5ca2013-08-07 11:05:11 +01001257 if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && options & WrapAround) {
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001258 searchRange = rangeOfContents(m_frame.document());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001259 resultRange = findPlainText(searchRange.get(), target, options);
1260 // We used to return false here if we ended up with the same range that we started with
1261 // (e.g., the reference range was already the only instance of this text). But we decided that
1262 // this should be a success case instead, so we'll just fall through in that case.
1263 }
1264
Ben Murdoch1fad5ca2013-08-07 11:05:11 +01001265 return resultRange->collapsed(ASSERT_NO_EXCEPTION) ? 0 : resultRange.release();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001266}
1267
1268void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
1269{
1270 if (flag == m_areMarkedTextMatchesHighlighted)
1271 return;
1272
1273 m_areMarkedTextMatchesHighlighted = flag;
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001274 m_frame.document()->markers()->repaintMarkers(DocumentMarker::TextMatch);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001275}
1276
1277void Editor::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
1278{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001279 spellChecker().respondToChangedSelection(oldSelection, options);
1280 m_frame.inputMethodController().cancelCompositionIfSelectionIsInvalid();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001281 notifyComponentsOnChangedSelection(oldSelection, options);
1282}
1283
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001284SpellChecker& Editor::spellChecker() const
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +01001285{
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001286 return m_frame.spellChecker();
Ben Murdoch3c9e4ae2013-08-12 14:20:44 +01001287}
1288
Ben Murdoch591b9582013-07-10 11:41:44 +01001289void Editor::toggleOverwriteModeEnabled()
1290{
1291 m_overwriteModeEnabled = !m_overwriteModeEnabled;
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +01001292 frame().selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
Torne (Richard Coles)1e202182013-10-18 15:46:42 +01001293}
Ben Murdoch591b9582013-07-10 11:41:44 +01001294
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001295} // namespace WebCore