4a24a7bf646066b296d9d6d40e39fdf76f5f7337
[WebKit-https.git] / Source / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2011, 2013-2015 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 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 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
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "Editor.h"
29
30 #include "AXObjectCache.h"
31 #include "AlternativeTextController.h"
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSPropertyNames.h"
35 #include "CachedResourceLoader.h"
36 #include "ClipboardEvent.h"
37 #include "CompositionEvent.h"
38 #include "CreateLinkCommand.h"
39 #include "DataTransfer.h"
40 #include "DeleteSelectionCommand.h"
41 #include "DictationAlternative.h"
42 #include "DictationCommand.h"
43 #include "DocumentFragment.h"
44 #include "DocumentMarkerController.h"
45 #include "EditorClient.h"
46 #include "EventHandler.h"
47 #include "EventNames.h"
48 #include "ExceptionCodePlaceholder.h"
49 #include "FocusController.h"
50 #include "Frame.h"
51 #include "FrameTree.h"
52 #include "FrameView.h"
53 #include "GraphicsContext.h"
54 #include "HTMLCollection.h"
55 #include "HTMLFormControlElement.h"
56 #include "HTMLFrameOwnerElement.h"
57 #include "HTMLImageElement.h"
58 #include "HTMLNames.h"
59 #include "HTMLTextAreaElement.h"
60 #include "HitTestResult.h"
61 #include "IndentOutdentCommand.h"
62 #include "InsertListCommand.h"
63 #include "KeyboardEvent.h"
64 #include "KillRing.h"
65 #include "Logging.h"
66 #include "MainFrame.h"
67 #include "ModifySelectionListLevel.h"
68 #include "NodeList.h"
69 #include "NodeTraversal.h"
70 #include "Page.h"
71 #include "Pasteboard.h"
72 #include "Range.h"
73 #include "RemoveFormatCommand.h"
74 #include "RenderBlock.h"
75 #include "RenderTextControl.h"
76 #include "RenderedDocumentMarker.h"
77 #include "RenderedPosition.h"
78 #include "ReplaceSelectionCommand.h"
79 #include "Settings.h"
80 #include "ShadowRoot.h"
81 #include "SimplifyMarkupCommand.h"
82 #include "Sound.h"
83 #include "SpellChecker.h"
84 #include "SpellingCorrectionCommand.h"
85 #include "StyleProperties.h"
86 #include "TelephoneNumberDetector.h"
87 #include "Text.h"
88 #include "TextCheckerClient.h"
89 #include "TextCheckingHelper.h"
90 #include "TextEvent.h"
91 #include "TextIterator.h"
92 #include "TypingCommand.h"
93 #include "UserTypingGestureIndicator.h"
94 #include "VisibleUnits.h"
95 #include "htmlediting.h"
96 #include "markup.h"
97 #include <wtf/unicode/CharacterNames.h>
98
99 #if PLATFORM(IOS)
100 #include "DictationCommandIOS.h"
101 #include <wtf/text/StringBuilder.h>
102 #include <wtf/text/WTFString.h>
103 #endif
104
105 #if PLATFORM(MAC)
106 #include "ServicesOverlayController.h"
107 #endif
108
109 namespace WebCore {
110
111 class ClearTextCommand : public DeleteSelectionCommand {
112 public:
113     ClearTextCommand(Document& document);
114     static void CreateAndApply(const RefPtr<Frame> frame);
115     
116 private:
117     virtual EditAction editingAction() const;
118 };
119
120 ClearTextCommand::ClearTextCommand(Document& document)
121     : DeleteSelectionCommand(document, false, true, false, false, true)
122 {
123 }
124
125 EditAction ClearTextCommand::editingAction() const
126 {
127     return EditActionDelete;
128 }
129
130 void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
131 {
132     if (frame->selection().isNone())
133         return;
134
135     // Don't leave around stale composition state.
136     frame->editor().clear();
137     
138     const VisibleSelection oldSelection = frame->selection().selection();
139     frame->selection().selectAll();
140     auto clearCommand = adoptRef(*new ClearTextCommand(*frame->document()));
141     clearCommand->setStartingSelection(oldSelection);
142     applyCommand(WTFMove(clearCommand));
143 }
144
145 using namespace HTMLNames;
146 using namespace WTF;
147 using namespace Unicode;
148
149 // When an event handler has moved the selection outside of a text control
150 // we should use the target control's selection for this editing operation.
151 VisibleSelection Editor::selectionForCommand(Event* event)
152 {
153     VisibleSelection selection = m_frame.selection().selection();
154     if (!event)
155         return selection;
156     // If the target is a text control, and the current selection is outside of its shadow tree,
157     // then use the saved selection for that text control.
158     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
159     HTMLTextFormControlElement* textFromControlOfTarget = is<HTMLTextFormControlElement>(*event->target()->toNode()) ? downcast<HTMLTextFormControlElement>(event->target()->toNode()) : nullptr;
160     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
161         if (RefPtr<Range> range = textFromControlOfTarget->selection())
162             return VisibleSelection(*range, DOWNSTREAM, selection.isDirectional());
163     }
164     return selection;
165 }
166
167 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
168 EditingBehavior Editor::behavior() const
169 {
170     return EditingBehavior(m_frame.settings().editingBehaviorType());
171 }
172
173 EditorClient* Editor::client() const
174 {
175     if (Page* page = m_frame.page())
176         return &page->editorClient();
177     return nullptr;
178 }
179
180 TextCheckerClient* Editor::textChecker() const
181 {
182     if (EditorClient* owner = client())
183         return owner->textChecker();
184     return 0;
185 }
186
187 void Editor::handleKeyboardEvent(KeyboardEvent& event)
188 {
189     if (EditorClient* c = client())
190         c->handleKeyboardEvent(&event);
191 }
192
193 void Editor::handleInputMethodKeydown(KeyboardEvent& event)
194 {
195     if (EditorClient* c = client())
196         c->handleInputMethodKeydown(&event);
197 }
198
199 bool Editor::handleTextEvent(TextEvent& event)
200 {
201     LOG(Editing, "Editor %p handleTextEvent (data %s)", this, event.data().utf8().data());
202
203     // Default event handling for Drag and Drop will be handled by DragController
204     // so we leave the event for it.
205     if (event.isDrop())
206         return false;
207
208     if (event.isPaste()) {
209         if (event.pastingFragment())
210 #if PLATFORM(IOS)
211         {
212             if (client()->performsTwoStepPaste(event.pastingFragment()))
213                 return true;
214 #endif
215             replaceSelectionWithFragment(event.pastingFragment(), false, event.shouldSmartReplace(), event.shouldMatchStyle(), EditActionPaste, event.mailBlockquoteHandling());
216 #if PLATFORM(IOS)
217         }
218 #endif
219         else 
220             replaceSelectionWithText(event.data(), false, event.shouldSmartReplace(), EditActionPaste);
221         return true;
222     }
223
224     String data = event.data();
225     if (data == "\n") {
226         if (event.isLineBreak())
227             return insertLineBreak();
228         return insertParagraphSeparator();
229     }
230
231     return insertTextWithoutSendingTextEvent(data, false, &event);
232 }
233
234 bool Editor::canEdit() const
235 {
236     return m_frame.selection().selection().rootEditableElement();
237 }
238
239 bool Editor::canEditRichly() const
240 {
241     return m_frame.selection().selection().isContentRichlyEditable();
242 }
243
244 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
245 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
246 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
247 // normally selectable to implement copy/paste (like divs, or a document body).
248
249 bool Editor::canDHTMLCut()
250 {
251     return !m_frame.selection().selection().isInPasswordField() && !dispatchCPPEvent(eventNames().beforecutEvent, DataTransferAccessPolicy::Numb);
252 }
253
254 bool Editor::canDHTMLCopy()
255 {
256     return !m_frame.selection().selection().isInPasswordField() && !dispatchCPPEvent(eventNames().beforecopyEvent, DataTransferAccessPolicy::Numb);
257 }
258
259 bool Editor::canDHTMLPaste()
260 {
261     return !dispatchCPPEvent(eventNames().beforepasteEvent, DataTransferAccessPolicy::Numb);
262 }
263
264 bool Editor::canCut() const
265 {
266     return canCopy() && canDelete();
267 }
268
269 static HTMLImageElement* imageElementFromImageDocument(Document& document)
270 {
271     if (!document.isImageDocument())
272         return nullptr;
273     
274     HTMLElement* body = document.bodyOrFrameset();
275     if (!body)
276         return nullptr;
277     
278     Node* node = body->firstChild();
279     if (!is<HTMLImageElement>(node))
280         return nullptr;
281     return downcast<HTMLImageElement>(node);
282 }
283
284 bool Editor::canCopy() const
285 {
286     if (imageElementFromImageDocument(document()))
287         return true;
288     const VisibleSelection& selection = m_frame.selection().selection();
289     return selection.isRange() && !selection.isInPasswordField();
290 }
291
292 bool Editor::canPaste() const
293 {
294     return canEdit();
295 }
296
297 bool Editor::canDelete() const
298 {
299     const VisibleSelection& selection = m_frame.selection().selection();
300     return selection.isRange() && selection.rootEditableElement();
301 }
302
303 bool Editor::canDeleteRange(Range* range) const
304 {
305     Node& startContainer = range->startContainer();
306     Node& endContainer = range->endContainer();
307     
308     if (!startContainer.hasEditableStyle() || !endContainer.hasEditableStyle())
309         return false;
310
311     if (range->collapsed()) {
312         VisiblePosition start(range->startPosition(), DOWNSTREAM);
313         VisiblePosition previous = start.previous();
314         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
315         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer.rootEditableElement())
316             return false;
317     }
318     return true;
319 }
320
321 bool Editor::smartInsertDeleteEnabled()
322 {   
323     return client() && client()->smartInsertDeleteEnabled();
324 }
325     
326 bool Editor::canSmartCopyOrDelete()
327 {
328     return client() && client()->smartInsertDeleteEnabled() && m_frame.selection().granularity() == WordGranularity;
329 }
330
331 bool Editor::isSelectTrailingWhitespaceEnabled()
332 {
333     return client() && client()->isSelectTrailingWhitespaceEnabled();
334 }
335
336 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool shouldAddToKillRing, bool isTypingAction)
337 {
338     if (!canEdit())
339         return false;
340
341     if (m_frame.selection().isRange()) {
342         if (isTypingAction) {
343             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
344             revealSelectionAfterEditingOperation();
345         } else {
346             if (shouldAddToKillRing)
347                 addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
348             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
349             // Implicitly calls revealSelectionAfterEditingOperation().
350         }
351     } else {
352         TypingCommand::Options options = 0;
353         if (canSmartCopyOrDelete())
354             options |= TypingCommand::SmartDelete;
355         if (shouldAddToKillRing)
356             options |= TypingCommand::AddsToKillRing;
357         switch (direction) {
358         case DirectionForward:
359         case DirectionRight:
360             TypingCommand::forwardDeleteKeyPressed(document(), options, granularity);
361             break;
362         case DirectionBackward:
363         case DirectionLeft:
364             TypingCommand::deleteKeyPressed(document(), options, granularity);
365             break;
366         }
367         revealSelectionAfterEditingOperation();
368     }
369
370     // FIXME: We should to move this down into deleteKeyPressed.
371     // clear the "start new kill ring sequence" setting, because it was set to true
372     // when the selection was updated by deleting the range
373     if (shouldAddToKillRing)
374         setStartNewKillRingSequence(false);
375
376     return true;
377 }
378
379 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editingAction)
380 {
381     if (m_frame.selection().isNone())
382         return;
383
384     applyCommand(DeleteSelectionCommand::create(document(), smartDelete, true, false, false, true, editingAction));
385 }
386
387 void Editor::clearText()
388 {
389     ClearTextCommand::CreateAndApply(&m_frame);
390 }
391
392 #if PLATFORM(IOS)
393
394 void Editor::insertDictationPhrases(Vector<Vector<String>>&& dictationPhrases, RetainPtr<id> metadata)
395 {
396     if (m_frame.selection().isNone())
397         return;
398
399     if (dictationPhrases.isEmpty())
400         return;
401
402     applyCommand(DictationCommandIOS::create(document(), WTFMove(dictationPhrases), WTFMove(metadata)));
403 }
404
405 void Editor::setDictationPhrasesAsChildOfElement(const Vector<Vector<String>>& dictationPhrases, RetainPtr<id> metadata, Element& element)
406 {
407     // Clear the composition.
408     clear();
409     
410     // Clear the Undo stack, since the operations that follow are not Undoable, and will corrupt the stack.  Some day
411     // we could make them Undoable, and let callers clear the Undo stack explicitly if they wish.
412     clearUndoRedoOperations();
413     
414     m_frame.selection().clear();
415     
416     element.removeChildren();
417     
418     if (dictationPhrases.isEmpty()) {
419         client()->respondToChangedContents();
420         return;
421     }
422     
423     ExceptionCode ec;    
424     RefPtr<Range> context = document().createRange();
425     context->selectNodeContents(element, ec);
426
427     StringBuilder dictationPhrasesBuilder;
428     for (auto& interpretations : dictationPhrases)
429         dictationPhrasesBuilder.append(interpretations[0]);
430
431     element.appendChild(createFragmentFromText(*context, dictationPhrasesBuilder.toString()), ec);
432
433     // We need a layout in order to add markers below.
434     document().updateLayout();
435
436     if (!element.firstChild()->isTextNode()) {
437         // Shouldn't happen.
438         ASSERT(element.firstChild()->isTextNode());
439         return;
440     }
441
442     Text& textNode = downcast<Text>(*element.firstChild());
443     int previousDictationPhraseStart = 0;
444     for (auto& interpretations : dictationPhrases) {
445         int dictationPhraseLength = interpretations[0].length();
446         int dictationPhraseEnd = previousDictationPhraseStart + dictationPhraseLength;
447         if (interpretations.size() > 1) {
448             auto dictationPhraseRange = Range::create(document(), &textNode, previousDictationPhraseStart, &textNode, dictationPhraseEnd);
449             document().markers().addDictationPhraseWithAlternativesMarker(dictationPhraseRange.ptr(), interpretations);
450         }
451         previousDictationPhraseStart = dictationPhraseEnd;
452     }
453
454     auto resultRange = Range::create(document(), &textNode, 0, &textNode, textNode.length());
455     document().markers().addDictationResultMarker(resultRange.ptr(), metadata);
456
457     client()->respondToChangedContents();
458 }
459
460 #endif
461
462 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
463 {
464     Node* target = findEventTargetFromSelection();
465     if (!target)
466         return;
467     target->dispatchEvent(TextEvent::createForPlainTextPaste(document().domWindow(), pastingText, smartReplace));
468 }
469
470 void Editor::pasteAsFragment(Ref<DocumentFragment>&& pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
471 {
472     Node* target = findEventTargetFromSelection();
473     if (!target)
474         return;
475     target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), WTFMove(pastingFragment), smartReplace, matchStyle, respectsMailBlockquote));
476 }
477
478 void Editor::pasteAsPlainTextBypassingDHTML()
479 {
480     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
481 }
482
483 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard& pasteboard)
484 {
485     String text = readPlainTextFromPasteboard(pasteboard);
486     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertActionPasted))
487         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
488 }
489
490 String Editor::readPlainTextFromPasteboard(Pasteboard& pasteboard)
491 {
492     PasteboardPlainText text;
493     pasteboard.read(text);
494     return plainTextFromPasteboard(text);
495 }
496
497 #if !PLATFORM(MAC)
498
499 String Editor::plainTextFromPasteboard(const PasteboardPlainText& text)
500 {
501     return text.text;
502 }
503
504 #endif
505
506 bool Editor::canSmartReplaceWithPasteboard(Pasteboard& pasteboard)
507 {
508     return client() && client()->smartInsertDeleteEnabled() && pasteboard.canSmartReplace();
509 }
510
511 bool Editor::shouldInsertFragment(PassRefPtr<DocumentFragment> fragment, PassRefPtr<Range> replacingDOMRange, EditorInsertAction givenAction)
512 {
513     if (!client())
514         return false;
515     
516     if (fragment) {
517         Node* child = fragment->firstChild();
518         if (is<CharacterData>(child) && fragment->lastChild() == child)
519             return client()->shouldInsertText(downcast<CharacterData>(*child).data(), replacingDOMRange.get(), givenAction);
520     }
521
522     return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
523 }
524
525 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
526 {
527     VisibleSelection selection = m_frame.selection().selection();
528     if (selection.isNone() || !selection.isContentEditable() || !fragment)
529         return;
530
531     AccessibilityReplacedText replacedText;
532     if (AXObjectCache::accessibilityEnabled() && editingAction == EditActionPaste)
533         replacedText = AccessibilityReplacedText(selection);
534
535     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
536     if (selectReplacement)
537         options |= ReplaceSelectionCommand::SelectReplacement;
538     if (smartReplace)
539         options |= ReplaceSelectionCommand::SmartReplace;
540     if (matchStyle)
541         options |= ReplaceSelectionCommand::MatchStyle;
542     if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
543         options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
544
545     RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document(), fragment, options, editingAction);
546     applyCommand(command);
547     revealSelectionAfterEditingOperation();
548
549     selection = m_frame.selection().selection();
550     if (selection.isInPasswordField())
551         return;
552
553     if (AXObjectCache::accessibilityEnabled() && editingAction == EditActionPaste) {
554         String text = AccessibilityObject::stringForVisiblePositionRange(command->visibleSelectionForInsertedText());
555         replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypePaste, text, m_frame.selection().selection());
556         command->composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
557     }
558
559     if (!isContinuousSpellCheckingEnabled())
560         return;
561
562     Node* nodeToCheck = selection.rootEditableElement();
563     if (!nodeToCheck)
564         return;
565
566     RefPtr<Range> rangeToCheck = Range::create(document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
567     m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck, rangeToCheck));
568 }
569
570 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace, EditAction editingAction)
571 {
572     RefPtr<Range> range = selectedRange();
573     if (!range)
574         return;
575
576     replaceSelectionWithFragment(createFragmentFromText(*range, text), selectReplacement, smartReplace, true, editingAction);
577 }
578
579 RefPtr<Range> Editor::selectedRange()
580 {
581     return m_frame.selection().toNormalizedRange();
582 }
583
584 #if PLATFORM(IOS)
585 void Editor::confirmMarkedText()
586 {
587     // FIXME: This is a hacky workaround for the keyboard calling this method too late -
588     // after the selection and focus have already changed.  See <rdar://problem/5975559>
589     Element* focused = document().focusedElement();
590     Node* composition = compositionNode();
591     
592     if (composition && focused && focused != composition && !composition->isDescendantOrShadowDescendantOf(focused)) {
593         cancelComposition();
594         document().setFocusedElement(focused);
595     } else
596         confirmComposition();
597 }
598
599 void Editor::setTextAsChildOfElement(const String& text, Element& element)
600 {
601     // Clear the composition
602     clear();
603     
604     // Clear the Undo stack, since the operations that follow are not Undoable, and will corrupt the stack.  Some day
605     // we could make them Undoable, and let callers clear the Undo stack explicitly if they wish.
606     clearUndoRedoOperations();
607     
608     // If the element is empty already and we're not adding text, we can early return and avoid clearing/setting
609     // a selection at [0, 0] and the expense involved in creation VisiblePositions.
610     if (!element.firstChild() && text.isEmpty())
611         return;
612     
613     // As a side effect this function sets a caret selection after the inserted content.  Much of what 
614     // follows is more expensive if there is a selection, so clear it since it's going to change anyway.
615     m_frame.selection().clear();
616     
617     // clear out all current children of element
618     element.removeChildren();
619
620     if (text.length()) {
621         // insert new text
622         // remove element from tree while doing it
623         // FIXME: The element we're inserting into is often the body element.  It seems strange to be removing it
624         // (even if it is only temporary).  ReplaceSelectionCommand doesn't bother doing this when it inserts
625         // content, why should we here?
626         ExceptionCode ec;
627         RefPtr<Node> parent = element.parentNode();
628         RefPtr<Node> siblingAfter = element.nextSibling();
629         if (parent)
630             element.remove(ec);
631             
632         auto context = document().createRange();
633         context->selectNodeContents(element, ec);
634         element.appendChild(createFragmentFromText(context, text), ec);
635     
636         // restore element to document
637         if (parent) {
638             if (siblingAfter)
639                 parent->insertBefore(element, siblingAfter.get(), ec);
640             else
641                 parent->appendChild(element, ec);
642         }
643     }
644
645     // set the selection to the end
646     VisibleSelection selection;
647
648     Position pos = createLegacyEditingPosition(&element, element.countChildNodes());
649
650     VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
651     if (visiblePos.isNull())
652         return;
653
654     selection.setBase(visiblePos);
655     selection.setExtent(visiblePos);
656      
657     m_frame.selection().setSelection(selection);
658     
659     client()->respondToChangedContents();
660 }
661 #endif
662
663 bool Editor::shouldDeleteRange(Range* range) const
664 {
665     if (!range || range->collapsed())
666         return false;
667     
668     if (!canDeleteRange(range))
669         return false;
670
671     return client() && client()->shouldDeleteRange(range);
672 }
673
674 bool Editor::tryDHTMLCopy()
675 {   
676     if (m_frame.selection().selection().isInPasswordField())
677         return false;
678
679     return !dispatchCPPEvent(eventNames().copyEvent, DataTransferAccessPolicy::Writable);
680 }
681
682 bool Editor::tryDHTMLCut()
683 {
684     if (m_frame.selection().selection().isInPasswordField())
685         return false;
686     
687     return !dispatchCPPEvent(eventNames().cutEvent, DataTransferAccessPolicy::Writable);
688 }
689
690 bool Editor::tryDHTMLPaste()
691 {
692     return !dispatchCPPEvent(eventNames().pasteEvent, DataTransferAccessPolicy::Readable);
693 }
694
695 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
696 {
697     return client() && client()->shouldInsertText(text, range, action);
698 }
699
700 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
701 {
702     if (AXObjectCache::accessibilityEnabled()) {
703         Node* node = endingSelection.start().deprecatedNode();
704         if (AXObjectCache* cache = document().existingAXObjectCache())
705             cache->postNotification(node, AXObjectCache::AXValueChanged, TargetObservableParent);
706     }
707
708     updateMarkersForWordsAffectedByEditing(true);
709
710     if (client())
711         client()->respondToChangedContents();
712 }
713
714 bool Editor::hasBidiSelection() const
715 {
716     if (m_frame.selection().isNone())
717         return false;
718
719     Node* startNode;
720     if (m_frame.selection().isRange()) {
721         startNode = m_frame.selection().selection().start().downstream().deprecatedNode();
722         Node* endNode = m_frame.selection().selection().end().upstream().deprecatedNode();
723         if (enclosingBlock(startNode) != enclosingBlock(endNode))
724             return false;
725     } else
726         startNode = m_frame.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
727
728     if (!startNode)
729         return false;
730
731     auto renderer = startNode->renderer();
732     while (renderer && !is<RenderBlockFlow>(*renderer))
733         renderer = renderer->parent();
734
735     if (!renderer)
736         return false;
737
738     if (!renderer->style().isLeftToRightDirection())
739         return true;
740
741     return downcast<RenderBlockFlow>(*renderer).containsNonZeroBidiLevel();
742 }
743
744 TriState Editor::selectionUnorderedListState() const
745 {
746     if (m_frame.selection().isCaret()) {
747         if (enclosingElementWithTag(m_frame.selection().selection().start(), ulTag))
748             return TrueTriState;
749     } else if (m_frame.selection().isRange()) {
750         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), ulTag);
751         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), ulTag);
752         if (startNode && endNode && startNode == endNode)
753             return TrueTriState;
754     }
755
756     return FalseTriState;
757 }
758
759 TriState Editor::selectionOrderedListState() const
760 {
761     if (m_frame.selection().isCaret()) {
762         if (enclosingElementWithTag(m_frame.selection().selection().start(), olTag))
763             return TrueTriState;
764     } else if (m_frame.selection().isRange()) {
765         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), olTag);
766         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), olTag);
767         if (startNode && endNode && startNode == endNode)
768             return TrueTriState;
769     }
770
771     return FalseTriState;
772 }
773
774 PassRefPtr<Node> Editor::insertOrderedList()
775 {
776     if (!canEditRichly())
777         return 0;
778         
779     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::OrderedList);
780     revealSelectionAfterEditingOperation();
781     return newList;
782 }
783
784 PassRefPtr<Node> Editor::insertUnorderedList()
785 {
786     if (!canEditRichly())
787         return 0;
788         
789     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::UnorderedList);
790     revealSelectionAfterEditingOperation();
791     return newList;
792 }
793
794 bool Editor::canIncreaseSelectionListLevel()
795 {
796     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(&document());
797 }
798
799 bool Editor::canDecreaseSelectionListLevel()
800 {
801     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(&document());
802 }
803
804 RefPtr<Node> Editor::increaseSelectionListLevel()
805 {
806     if (!canEditRichly() || m_frame.selection().isNone())
807         return nullptr;
808     
809     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(&document());
810     revealSelectionAfterEditingOperation();
811     return newList;
812 }
813
814 RefPtr<Node> Editor::increaseSelectionListLevelOrdered()
815 {
816     if (!canEditRichly() || m_frame.selection().isNone())
817         return nullptr;
818     
819     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(&document());
820     revealSelectionAfterEditingOperation();
821     return newList;
822 }
823
824 RefPtr<Node> Editor::increaseSelectionListLevelUnordered()
825 {
826     if (!canEditRichly() || m_frame.selection().isNone())
827         return nullptr;
828     
829     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(&document());
830     revealSelectionAfterEditingOperation();
831     return newList;
832 }
833
834 void Editor::decreaseSelectionListLevel()
835 {
836     if (!canEditRichly() || m_frame.selection().isNone())
837         return;
838     
839     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(&document());
840     revealSelectionAfterEditingOperation();
841 }
842
843 void Editor::removeFormattingAndStyle()
844 {
845     applyCommand(RemoveFormatCommand::create(document()));
846 }
847
848 void Editor::clearLastEditCommand() 
849 {
850     m_lastEditCommand = nullptr;
851 }
852 #if PLATFORM(IOS)
853 // If the selection is adjusted from UIKit without closing the typing, the typing command may
854 // have a stale selection.
855 void Editor::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping()
856 {
857     TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(&m_frame, m_frame.selection().selection());
858 }
859 #endif
860
861 // Returns whether caller should continue with "the default processing", which is the same as 
862 // the event handler NOT setting the return value to false
863 bool Editor::dispatchCPPEvent(const AtomicString& eventType, DataTransferAccessPolicy policy)
864 {
865     Node* target = findEventTargetFromSelection();
866     if (!target)
867         return true;
868
869     RefPtr<DataTransfer> dataTransfer = DataTransfer::createForCopyAndPaste(policy);
870
871     Ref<Event> event = ClipboardEvent::create(eventType, true, true, dataTransfer.get());
872     target->dispatchEvent(event);
873     bool noDefaultProcessing = event->defaultPrevented();
874     if (noDefaultProcessing && policy == DataTransferAccessPolicy::Writable) {
875         auto pasteboard = Pasteboard::createForCopyAndPaste();
876         pasteboard->clear();
877         pasteboard->writePasteboard(dataTransfer->pasteboard());
878     }
879
880     // invalidate dataTransfer here for security
881     dataTransfer->setAccessPolicy(DataTransferAccessPolicy::Numb);
882     
883     return !noDefaultProcessing;
884 }
885
886 Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const
887 {
888     Node* target = selection.start().element();
889     if (!target)
890         target = document().bodyOrFrameset();
891     if (!target)
892         return nullptr;
893
894     return target;
895 }
896
897 Node* Editor::findEventTargetFromSelection() const
898 {
899     return findEventTargetFrom(m_frame.selection().selection());
900 }
901
902 void Editor::applyStyle(StyleProperties* style, EditAction editingAction)
903 {
904     switch (m_frame.selection().selection().selectionType()) {
905     case VisibleSelection::NoSelection:
906         return;
907     case VisibleSelection::CaretSelection:
908         computeAndSetTypingStyle(EditingStyle::create(style), editingAction);
909         break;
910     case VisibleSelection::RangeSelection:
911         if (style)
912             applyCommand(ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction));
913         break;
914     }
915     client()->didApplyStyle();
916 }
917
918 void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction)
919 {
920     switch (m_frame.selection().selection().selectionType()) {
921     case VisibleSelection::NoSelection:
922         return;
923     case VisibleSelection::CaretSelection:
924         computeAndSetTypingStyle(*style, editingAction);
925         break;
926     case VisibleSelection::RangeSelection:
927         if (style)
928             applyCommand(ApplyStyleCommand::create(document(), style.get(), editingAction));
929         break;
930     }
931     client()->didApplyStyle();
932 }
933     
934 bool Editor::shouldApplyStyle(StyleProperties* style, Range* range)
935 {   
936     return client()->shouldApplyStyle(style, range);
937 }
938     
939 void Editor::applyParagraphStyle(StyleProperties* style, EditAction editingAction)
940 {
941     switch (m_frame.selection().selection().selectionType()) {
942     case VisibleSelection::NoSelection:
943         return;
944     case VisibleSelection::CaretSelection:
945     case VisibleSelection::RangeSelection:
946         if (style)
947             applyCommand(ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction, ApplyStyleCommand::ForceBlockProperties));
948         break;
949     }
950     client()->didApplyStyle();
951 }
952
953 void Editor::applyStyleToSelection(StyleProperties* style, EditAction editingAction)
954 {
955     if (!style || style->isEmpty() || !canEditRichly())
956         return;
957
958     if (!client() || !client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
959         return;
960     applyStyle(style, editingAction);
961 }
962
963 void Editor::applyStyleToSelection(Ref<EditingStyle>&& style, EditAction editingAction)
964 {
965     if (style->isEmpty() || !canEditRichly())
966         return;
967
968     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
969     if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), m_frame.selection().toNormalizedRange().get()))
970         return;
971
972     applyStyle(WTFMove(style), editingAction);
973 }
974
975 void Editor::applyParagraphStyleToSelection(StyleProperties* style, EditAction editingAction)
976 {
977     if (!style || style->isEmpty() || !canEditRichly())
978         return;
979     
980     if (client() && client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
981         applyParagraphStyle(style, editingAction);
982 }
983
984 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
985 {
986     return EditingStyle::create(propertyID, value)->triStateOfStyle(
987         EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor).get());
988 }
989
990 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
991 {
992     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
993 }
994
995 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
996 {
997     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
998         propertyID == CSSPropertyBackgroundColor);
999     if (!selectionStyle || !selectionStyle->style())
1000         return String();
1001
1002     if (propertyID == CSSPropertyFontSize)
1003         return String::number(selectionStyle->legacyFontSize(&document()));
1004     return selectionStyle->style()->getPropertyValue(propertyID);
1005 }
1006
1007 void Editor::indent()
1008 {
1009     applyCommand(IndentOutdentCommand::create(document(), IndentOutdentCommand::Indent));
1010 }
1011
1012 void Editor::outdent()
1013 {
1014     applyCommand(IndentOutdentCommand::create(document(), IndentOutdentCommand::Outdent));
1015 }
1016
1017 static void notifyTextFromControls(Element* startRoot, Element* endRoot)
1018 {
1019     HTMLTextFormControlElement* startingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(startRoot));
1020     HTMLTextFormControlElement* endingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(endRoot));
1021     if (startingTextControl)
1022         startingTextControl->didEditInnerTextValue();
1023     if (endingTextControl && startingTextControl != endingTextControl)
1024         endingTextControl->didEditInnerTextValue();
1025 }
1026
1027 static void dispatchEditableContentChangedEvents(PassRefPtr<Element> prpStartRoot, PassRefPtr<Element> prpEndRoot)
1028 {
1029     RefPtr<Element> startRoot = prpStartRoot;
1030     RefPtr<Element> endRoot = prpEndRoot;
1031     if (startRoot)
1032         startRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false));
1033     if (endRoot && endRoot != startRoot)
1034         endRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false));
1035 }
1036
1037 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
1038 {
1039     LOG(Editing, "Editor %p appliedEditing", this);
1040
1041     document().updateLayout();
1042
1043     EditCommandComposition* composition = cmd->composition();
1044     ASSERT(composition);
1045     VisibleSelection newSelection(cmd->endingSelection());
1046
1047     notifyTextFromControls(composition->startingRootEditableElement(), composition->endingRootEditableElement());
1048
1049     // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
1050     FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
1051     
1052     changeSelectionAfterCommand(newSelection, options);
1053     dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement());
1054
1055     updateEditorUINowIfScheduled();
1056     
1057     m_alternativeTextController->respondToAppliedEditing(cmd.get());
1058
1059     if (!cmd->preservesTypingStyle())
1060         m_frame.selection().clearTypingStyle();
1061
1062     // Command will be equal to last edit command only in the case of typing
1063     if (m_lastEditCommand.get() == cmd)
1064         ASSERT(cmd->isTypingCommand());
1065     else {
1066         // Only register a new undo command if the command passed in is
1067         // different from the last command
1068         m_lastEditCommand = cmd;
1069         if (client())
1070             client()->registerUndoStep(m_lastEditCommand->ensureComposition());
1071     }
1072
1073     respondToChangedContents(newSelection);
1074 }
1075
1076 void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd)
1077 {
1078     document().updateLayout();
1079
1080     notifyTextFromControls(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1081
1082     VisibleSelection newSelection(cmd->startingSelection());
1083     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1084     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1085
1086     updateEditorUINowIfScheduled();
1087
1088     m_alternativeTextController->respondToUnappliedEditing(cmd.get());
1089
1090     m_lastEditCommand = nullptr;
1091     if (client())
1092         client()->registerRedoStep(cmd);
1093     respondToChangedContents(newSelection);
1094 }
1095
1096 void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd)
1097 {
1098     document().updateLayout();
1099
1100     notifyTextFromControls(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1101
1102     VisibleSelection newSelection(cmd->endingSelection());
1103     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1104     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1105     
1106     updateEditorUINowIfScheduled();
1107
1108     m_lastEditCommand = nullptr;
1109     if (client())
1110         client()->registerUndoStep(cmd);
1111     respondToChangedContents(newSelection);
1112 }
1113
1114 Editor::Editor(Frame& frame)
1115     : m_frame(frame)
1116     , m_killRing(std::make_unique<KillRing>())
1117     , m_spellChecker(std::make_unique<SpellChecker>(frame))
1118     , m_alternativeTextController(std::make_unique<AlternativeTextController>(frame))
1119     , m_editorUIUpdateTimer(*this, &Editor::editorUIUpdateTimerFired)
1120 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
1121     , m_telephoneNumberDetectionUpdateTimer(*this, &Editor::scanSelectionForTelephoneNumbers)
1122 #endif
1123 {
1124 }
1125
1126 Editor::~Editor()
1127 {
1128 }
1129
1130 void Editor::clear()
1131 {
1132     if (m_compositionNode) {
1133         m_compositionNode = nullptr;
1134         if (EditorClient* client = this->client())
1135             client->discardedComposition(&m_frame);
1136     }
1137     m_customCompositionUnderlines.clear();
1138     m_shouldStyleWithCSS = false;
1139     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
1140 }
1141
1142 bool Editor::insertText(const String& text, Event* triggeringEvent)
1143 {
1144     return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent);
1145 }
1146
1147 bool Editor::insertTextForConfirmedComposition(const String& text)
1148 {
1149     return m_frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
1150 }
1151
1152 bool Editor::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent)
1153 {
1154     return m_alternativeTextController->insertDictatedText(text, dictationAlternatives, triggeringEvent);
1155 }
1156
1157 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
1158 {
1159     if (text.isEmpty())
1160         return false;
1161
1162     VisibleSelection selection = selectionForCommand(triggeringEvent);
1163     if (!selection.isContentEditable())
1164         return false;
1165     RefPtr<Range> range = selection.toNormalizedRange();
1166
1167     if (!shouldInsertText(text, range.get(), EditorInsertActionTyped))
1168         return true;
1169
1170     updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
1171
1172     bool shouldConsiderApplyingAutocorrection = false;
1173     if (text == " " || text == "\t")
1174         shouldConsiderApplyingAutocorrection = true;
1175
1176     if (text.length() == 1 && u_ispunct(text[0]) && !isAmbiguousBoundaryCharacter(text[0]))
1177         shouldConsiderApplyingAutocorrection = true;
1178
1179     bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1180
1181     // Get the selection to use for the event that triggered this insertText.
1182     // If the event handler changed the selection, we may want to use a different selection
1183     // that is contained in the event target.
1184     selection = selectionForCommand(triggeringEvent);
1185     if (selection.isContentEditable()) {
1186         if (Node* selectionStart = selection.start().deprecatedNode()) {
1187             Ref<Document> document(selectionStart->document());
1188
1189             // Insert the text
1190             if (triggeringEvent && triggeringEvent->isDictation())
1191                 DictationCommand::insertText(document, text, triggeringEvent->dictationAlternatives(), selection);
1192             else {
1193                 TypingCommand::Options options = 0;
1194                 if (selectInsertedText)
1195                     options |= TypingCommand::SelectInsertedText;
1196                 if (autocorrectionWasApplied)
1197                     options |= TypingCommand::RetainAutocorrectionIndicator;
1198                 TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
1199             }
1200
1201             // Reveal the current selection
1202             if (Frame* editedFrame = document->frame())
1203                 if (Page* page = editedFrame->page()) {
1204 #if PLATFORM(IOS)
1205                     SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
1206 #else
1207                     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
1208 #endif
1209                     page->focusController().focusedOrMainFrame().selection().revealSelection(revealMode, ScrollAlignment::alignCenterIfNeeded);
1210                 }
1211         }
1212     }
1213
1214     return true;
1215 }
1216
1217 bool Editor::insertLineBreak()
1218 {
1219     if (!canEdit())
1220         return false;
1221
1222     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertActionTyped))
1223         return true;
1224
1225     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1226     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1227     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1228     TypingCommand::insertLineBreak(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1229     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1230
1231     return true;
1232 }
1233
1234 bool Editor::insertParagraphSeparator()
1235 {
1236     if (!canEdit())
1237         return false;
1238
1239     if (!canEditRichly())
1240         return insertLineBreak();
1241
1242     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertActionTyped))
1243         return true;
1244
1245     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1246     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1247     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1248     TypingCommand::insertParagraphSeparator(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1249     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1250
1251     return true;
1252 }
1253
1254 bool Editor::insertParagraphSeparatorInQuotedContent()
1255 {
1256     // FIXME: Why is this missing calls to canEdit, canEditRichly, etc.?
1257     TypingCommand::insertParagraphSeparatorInQuotedContent(document());
1258     revealSelectionAfterEditingOperation();
1259     return true;
1260 }
1261
1262 void Editor::cut()
1263 {
1264     if (tryDHTMLCut())
1265         return; // DHTML did the whole operation
1266     if (!canCut()) {
1267         systemBeep();
1268         return;
1269     }
1270
1271     performCutOrCopy(CutAction);
1272 }
1273
1274 void Editor::copy()
1275 {
1276     if (tryDHTMLCopy())
1277         return; // DHTML did the whole operation
1278     if (!canCopy()) {
1279         systemBeep();
1280         return;
1281     }
1282
1283     performCutOrCopy(CopyAction);
1284 }
1285
1286 void Editor::postTextStateChangeNotificationForCut(const String& text, const VisibleSelection& selection)
1287 {
1288     if (!AXObjectCache::accessibilityEnabled())
1289         return;
1290     if (!text.length())
1291         return;
1292     AXObjectCache* cache = document().existingAXObjectCache();
1293     if (!cache)
1294         return;
1295     cache->postTextStateChangeNotification(selection.start().anchorNode(), AXTextEditTypeCut, text, selection.start());
1296 }
1297
1298 void Editor::performCutOrCopy(EditorActionSpecifier action)
1299 {
1300     RefPtr<Range> selection = selectedRange();
1301     willWriteSelectionToPasteboard(selection);
1302     if (action == CutAction) {
1303         if (!shouldDeleteRange(selection.get()))
1304             return;
1305
1306         updateMarkersForWordsAffectedByEditing(true);
1307     }
1308
1309     if (enclosingTextFormControl(m_frame.selection().selection().start()))
1310         Pasteboard::createForCopyAndPaste()->writePlainText(selectedTextForDataTransfer(), canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
1311     else {
1312         HTMLImageElement* imageElement = nullptr;
1313         if (action == CopyAction)
1314             imageElement = imageElementFromImageDocument(document());
1315
1316         if (imageElement) {
1317 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1318             writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *imageElement, document().url(), document().title());
1319 #else
1320             Pasteboard::createForCopyAndPaste()->writeImage(*imageElement, document().url(), document().title());
1321 #endif
1322         } else {
1323 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1324             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
1325 #else
1326             // FIXME: Convert all other platforms to match Mac and delete this.
1327             Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForDataTransfer);
1328 #endif
1329         }
1330     }
1331
1332     didWriteSelectionToPasteboard();
1333     if (action == CutAction) {
1334         String text;
1335         if (AXObjectCache::accessibilityEnabled())
1336             text = AccessibilityObject::stringForVisiblePositionRange(m_frame.selection().selection());
1337         deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), EditActionCut);
1338         if (AXObjectCache::accessibilityEnabled())
1339             postTextStateChangeNotificationForCut(text, m_frame.selection().selection());
1340     }
1341 }
1342
1343 void Editor::paste()
1344 {
1345     paste(*Pasteboard::createForCopyAndPaste());
1346 }
1347
1348 void Editor::paste(Pasteboard& pasteboard)
1349 {
1350     if (tryDHTMLPaste())
1351         return; // DHTML did the whole operation
1352     if (!canPaste())
1353         return;
1354     updateMarkersForWordsAffectedByEditing(false);
1355     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
1356     if (m_frame.selection().selection().isContentRichlyEditable())
1357         pasteWithPasteboard(&pasteboard, true);
1358     else
1359         pasteAsPlainTextWithPasteboard(pasteboard);
1360 }
1361
1362 void Editor::pasteAsPlainText()
1363 {
1364     if (tryDHTMLPaste())
1365         return;
1366     if (!canPaste())
1367         return;
1368     updateMarkersForWordsAffectedByEditing(false);
1369     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
1370 }
1371
1372 void Editor::performDelete()
1373 {
1374     if (!canDelete()) {
1375         systemBeep();
1376         return;
1377     }
1378
1379     addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
1380     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
1381
1382     // clear the "start new kill ring sequence" setting, because it was set to true
1383     // when the selection was updated by deleting the range
1384     setStartNewKillRingSequence(false);
1385 }
1386
1387 void Editor::simplifyMarkup(Node* startNode, Node* endNode)
1388 {
1389     if (!startNode)
1390         return;
1391     if (endNode) {
1392         if (&startNode->document() != &endNode->document())
1393             return;
1394         // check if start node is before endNode
1395         Node* node = startNode;
1396         while (node && node != endNode)
1397             node = NodeTraversal::next(*node);
1398         if (!node)
1399             return;
1400     }
1401     
1402     applyCommand(SimplifyMarkupCommand::create(document(), startNode, endNode ? NodeTraversal::next(*endNode) : nullptr));
1403 }
1404
1405 void Editor::copyURL(const URL& url, const String& title)
1406 {
1407     copyURL(url, title, *Pasteboard::createForCopyAndPaste());
1408 }
1409
1410 void Editor::copyURL(const URL& url, const String& title, Pasteboard& pasteboard)
1411 {
1412     PasteboardURL pasteboardURL;
1413     pasteboardURL.url = url;
1414     pasteboardURL.title = title;
1415
1416 #if PLATFORM(MAC)
1417     fillInUserVisibleForm(pasteboardURL);
1418 #endif
1419
1420     pasteboard.write(pasteboardURL);
1421 }
1422
1423 #if !PLATFORM(IOS)
1424 void Editor::copyImage(const HitTestResult& result)
1425 {
1426     Element* element = result.innerNonSharedElement();
1427     if (!element)
1428         return;
1429
1430     URL url = result.absoluteLinkURL();
1431     if (url.isEmpty())
1432         url = result.absoluteImageURL();
1433
1434 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1435     writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *element, url, result.altDisplayString());
1436 #else
1437     Pasteboard::createForCopyAndPaste()->writeImage(*element, url, result.altDisplayString());
1438 #endif
1439 }
1440 #endif
1441
1442 bool Editor::isContinuousSpellCheckingEnabled() const
1443 {
1444     return client() && client()->isContinuousSpellCheckingEnabled();
1445 }
1446
1447 void Editor::toggleContinuousSpellChecking()
1448 {
1449     if (client())
1450         client()->toggleContinuousSpellChecking();
1451 }
1452
1453 bool Editor::isGrammarCheckingEnabled()
1454 {
1455     return client() && client()->isGrammarCheckingEnabled();
1456 }
1457
1458 void Editor::toggleGrammarChecking()
1459 {
1460     if (client())
1461         client()->toggleGrammarChecking();
1462 }
1463
1464 int Editor::spellCheckerDocumentTag()
1465 {
1466     return client() ? client()->spellCheckerDocumentTag() : 0;
1467 }
1468
1469 #if USE(APPKIT)
1470
1471 void Editor::uppercaseWord()
1472 {
1473     if (client())
1474         client()->uppercaseWord();
1475 }
1476
1477 void Editor::lowercaseWord()
1478 {
1479     if (client())
1480         client()->lowercaseWord();
1481 }
1482
1483 void Editor::capitalizeWord()
1484 {
1485     if (client())
1486         client()->capitalizeWord();
1487 }
1488     
1489 #endif
1490
1491 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1492
1493 void Editor::showSubstitutionsPanel()
1494 {
1495     if (!client()) {
1496         LOG_ERROR("No NSSpellChecker");
1497         return;
1498     }
1499
1500     if (client()->substitutionsPanelIsShowing()) {
1501         client()->showSubstitutionsPanel(false);
1502         return;
1503     }
1504     client()->showSubstitutionsPanel(true);
1505 }
1506
1507 bool Editor::substitutionsPanelIsShowing()
1508 {
1509     if (!client())
1510         return false;
1511     return client()->substitutionsPanelIsShowing();
1512 }
1513
1514 void Editor::toggleSmartInsertDelete()
1515 {
1516     if (client())
1517         client()->toggleSmartInsertDelete();
1518 }
1519
1520 bool Editor::isAutomaticQuoteSubstitutionEnabled()
1521 {
1522     return client() && client()->isAutomaticQuoteSubstitutionEnabled();
1523 }
1524
1525 void Editor::toggleAutomaticQuoteSubstitution()
1526 {
1527     if (client())
1528         client()->toggleAutomaticQuoteSubstitution();
1529 }
1530
1531 bool Editor::isAutomaticLinkDetectionEnabled()
1532 {
1533     return client() && client()->isAutomaticLinkDetectionEnabled();
1534 }
1535
1536 void Editor::toggleAutomaticLinkDetection()
1537 {
1538     if (client())
1539         client()->toggleAutomaticLinkDetection();
1540 }
1541
1542 bool Editor::isAutomaticDashSubstitutionEnabled()
1543 {
1544     return client() && client()->isAutomaticDashSubstitutionEnabled();
1545 }
1546
1547 void Editor::toggleAutomaticDashSubstitution()
1548 {
1549     if (client())
1550         client()->toggleAutomaticDashSubstitution();
1551 }
1552
1553 bool Editor::isAutomaticTextReplacementEnabled()
1554 {
1555     return client() && client()->isAutomaticTextReplacementEnabled();
1556 }
1557
1558 void Editor::toggleAutomaticTextReplacement()
1559 {
1560     if (client())
1561         client()->toggleAutomaticTextReplacement();
1562 }
1563
1564 bool Editor::isAutomaticSpellingCorrectionEnabled()
1565 {
1566     return m_alternativeTextController->isAutomaticSpellingCorrectionEnabled();
1567 }
1568
1569 void Editor::toggleAutomaticSpellingCorrection()
1570 {
1571     if (client())
1572         client()->toggleAutomaticSpellingCorrection();
1573 }
1574
1575 #endif
1576
1577 bool Editor::shouldEndEditing(Range* range)
1578 {
1579     return client() && client()->shouldEndEditing(range);
1580 }
1581
1582 bool Editor::shouldBeginEditing(Range* range)
1583 {
1584     return client() && client()->shouldBeginEditing(range);
1585 }
1586
1587 void Editor::clearUndoRedoOperations()
1588 {
1589     if (client())
1590         client()->clearUndoRedoOperations();
1591 }
1592
1593 bool Editor::canUndo()
1594 {
1595     return client() && client()->canUndo();
1596 }
1597
1598 void Editor::undo()
1599 {
1600     if (client())
1601         client()->undo();
1602 }
1603
1604 bool Editor::canRedo()
1605 {
1606     return client() && client()->canRedo();
1607 }
1608
1609 void Editor::redo()
1610 {
1611     if (client())
1612         client()->redo();
1613 }
1614
1615 void Editor::didBeginEditing()
1616 {
1617     if (client())
1618         client()->didBeginEditing();
1619 }
1620
1621 void Editor::didEndEditing()
1622 {
1623     if (client())
1624         client()->didEndEditing();
1625 }
1626
1627 void Editor::willWriteSelectionToPasteboard(PassRefPtr<Range> range)
1628 {
1629     if (client())
1630         client()->willWriteSelectionToPasteboard(range.get());
1631 }
1632
1633 void Editor::didWriteSelectionToPasteboard()
1634 {
1635     if (client())
1636         client()->didWriteSelectionToPasteboard();
1637 }
1638
1639 void Editor::toggleBold()
1640 {
1641     command("ToggleBold").execute();
1642 }
1643
1644 void Editor::toggleUnderline()
1645 {
1646     command("ToggleUnderline").execute();
1647 }
1648
1649 void Editor::setBaseWritingDirection(WritingDirection direction)
1650 {
1651 #if PLATFORM(IOS)
1652     if (inSameParagraph(m_frame.selection().selection().visibleStart(), m_frame.selection().selection().visibleEnd()) && 
1653         baseWritingDirectionForSelectionStart() == direction)
1654         return;
1655 #endif
1656         
1657     Element* focusedElement = document().focusedElement();
1658     if (is<HTMLTextFormControlElement>(focusedElement)) {
1659         if (direction == NaturalWritingDirection)
1660             return;
1661         downcast<HTMLTextFormControlElement>(*focusedElement).setAttributeWithoutSynchronization(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
1662         focusedElement->dispatchInputEvent();
1663         document().updateStyleIfNeeded();
1664         return;
1665     }
1666
1667     RefPtr<MutableStyleProperties> style = MutableStyleProperties::create();
1668     style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
1669     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
1670 }
1671
1672 WritingDirection Editor::baseWritingDirectionForSelectionStart() const
1673 {
1674     WritingDirection result = LeftToRightWritingDirection;
1675
1676     Position pos = m_frame.selection().selection().visibleStart().deepEquivalent();
1677     Node* node = pos.deprecatedNode();
1678     if (!node)
1679         return result;
1680
1681     auto renderer = node->renderer();
1682     if (!renderer)
1683         return result;
1684
1685     if (!renderer->isRenderBlockFlow()) {
1686         renderer = renderer->containingBlock();
1687         if (!renderer)
1688             return result;
1689     }
1690
1691     switch (renderer->style().direction()) {
1692     case LTR:
1693         return LeftToRightWritingDirection;
1694     case RTL:
1695         return RightToLeftWritingDirection;
1696     }
1697     
1698     return result;
1699 }
1700
1701 void Editor::selectComposition()
1702 {
1703     RefPtr<Range> range = compositionRange();
1704     if (!range)
1705         return;
1706     
1707     // The composition can start inside a composed character sequence, so we have to override checks.
1708     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
1709     VisibleSelection selection;
1710     selection.setWithoutValidation(range->startPosition(), range->endPosition());
1711     m_frame.selection().setSelection(selection, 0);
1712 }
1713
1714 void Editor::confirmComposition()
1715 {
1716     if (!m_compositionNode)
1717         return;
1718     setComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
1719 }
1720
1721 void Editor::cancelComposition()
1722 {
1723     if (!m_compositionNode)
1724         return;
1725     setComposition(emptyString(), CancelComposition);
1726 }
1727
1728 bool Editor::cancelCompositionIfSelectionIsInvalid()
1729 {
1730     unsigned start;
1731     unsigned end;
1732     if (!hasComposition() || ignoreCompositionSelectionChange() || getCompositionSelection(start, end))
1733         return false;
1734
1735     cancelComposition();
1736     return true;
1737 }
1738
1739 void Editor::confirmComposition(const String& text)
1740 {
1741     setComposition(text, ConfirmComposition);
1742 }
1743
1744 void Editor::setComposition(const String& text, SetCompositionMode mode)
1745 {
1746     ASSERT(mode == ConfirmComposition || mode == CancelComposition);
1747     UserTypingGestureIndicator typingGestureIndicator(m_frame);
1748
1749     setIgnoreCompositionSelectionChange(true);
1750
1751     if (mode == CancelComposition)
1752         ASSERT(text == emptyString());
1753     else
1754         selectComposition();
1755
1756     if (m_frame.selection().isNone()) {
1757         setIgnoreCompositionSelectionChange(false);
1758         return;
1759     }
1760     
1761     // Dispatch a compositionend event to the focused node.
1762     // We should send this event before sending a TextEvent as written in Section 6.2.2 and 6.2.3 of
1763     // the DOM Event specification.
1764     if (Element* target = document().focusedElement()) {
1765         Ref<CompositionEvent> event = CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text);
1766         target->dispatchEvent(event);
1767     }
1768
1769     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
1770     // will delete the old composition with an optimized replace operation.
1771     if (text.isEmpty() && mode != CancelComposition)
1772         TypingCommand::deleteSelection(document(), 0);
1773
1774     m_compositionNode = nullptr;
1775     m_customCompositionUnderlines.clear();
1776
1777     insertTextForConfirmedComposition(text);
1778
1779     if (mode == CancelComposition) {
1780         // An open typing command that disagrees about current selection would cause issues with typing later on.
1781         TypingCommand::closeTyping(&m_frame);
1782     }
1783
1784     setIgnoreCompositionSelectionChange(false);
1785 }
1786
1787 void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
1788 {
1789     UserTypingGestureIndicator typingGestureIndicator(m_frame);
1790
1791     setIgnoreCompositionSelectionChange(true);
1792
1793     // Updates styles before setting selection for composition to prevent
1794     // inserting the previous composition text into text nodes oddly.
1795     // See https://bugs.webkit.org/show_bug.cgi?id=46868
1796     document().updateStyleIfNeeded();
1797
1798     selectComposition();
1799
1800     if (m_frame.selection().isNone()) {
1801         setIgnoreCompositionSelectionChange(false);
1802         return;
1803     }
1804
1805 #if PLATFORM(IOS)
1806     client()->startDelayingAndCoalescingContentChangeNotifications();
1807 #endif
1808
1809     Element* target = document().focusedElement();
1810     if (target) {
1811         // Dispatch an appropriate composition event to the focused node.
1812         // We check the composition status and choose an appropriate composition event since this
1813         // function is used for three purposes:
1814         // 1. Starting a new composition.
1815         //    Send a compositionstart and a compositionupdate event when this function creates
1816         //    a new composition node, i.e.
1817         //    m_compositionNode == 0 && !text.isEmpty().
1818         //    Sending a compositionupdate event at this time ensures that at least one
1819         //    compositionupdate event is dispatched.
1820         // 2. Updating the existing composition node.
1821         //    Send a compositionupdate event when this function updates the existing composition
1822         //    node, i.e. m_compositionNode != 0 && !text.isEmpty().
1823         // 3. Canceling the ongoing composition.
1824         //    Send a compositionend event when function deletes the existing composition node, i.e.
1825         //    m_compositionNode != 0 && test.isEmpty().
1826         RefPtr<CompositionEvent> event;
1827         if (!m_compositionNode) {
1828             // We should send a compositionstart event only when the given text is not empty because this
1829             // function doesn't create a composition node when the text is empty.
1830             if (!text.isEmpty()) {
1831                 target->dispatchEvent(CompositionEvent::create(eventNames().compositionstartEvent, document().domWindow(), selectedText()));
1832                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1833             }
1834         } else {
1835             if (!text.isEmpty())
1836                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1837             else
1838                 event = CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text);
1839         }
1840         if (event)
1841             target->dispatchEvent(*event);
1842     }
1843
1844     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
1845     // will delete the old composition with an optimized replace operation.
1846     if (text.isEmpty())
1847         TypingCommand::deleteSelection(document(), TypingCommand::PreventSpellChecking);
1848
1849     m_compositionNode = nullptr;
1850     m_customCompositionUnderlines.clear();
1851
1852     if (!text.isEmpty()) {
1853         TypingCommand::insertText(document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionUpdate);
1854
1855         // Find out what node has the composition now.
1856         Position base = m_frame.selection().selection().base().downstream();
1857         Position extent = m_frame.selection().selection().extent();
1858         Node* baseNode = base.deprecatedNode();
1859         unsigned baseOffset = base.deprecatedEditingOffset();
1860         Node* extentNode = extent.deprecatedNode();
1861         unsigned extentOffset = extent.deprecatedEditingOffset();
1862
1863         if (is<Text>(baseNode) && baseNode == extentNode && baseOffset + text.length() == extentOffset) {
1864             m_compositionNode = downcast<Text>(baseNode);
1865             m_compositionStart = baseOffset;
1866             m_compositionEnd = extentOffset;
1867             m_customCompositionUnderlines = underlines;
1868             for (auto& underline : m_customCompositionUnderlines) {
1869                 underline.startOffset += baseOffset;
1870                 underline.endOffset += baseOffset;
1871             }
1872             if (baseNode->renderer())
1873                 baseNode->renderer()->repaint();
1874
1875             unsigned start = std::min(baseOffset + selectionStart, extentOffset);
1876             unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
1877             RefPtr<Range> selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
1878             m_frame.selection().setSelectedRange(selectedRange.get(), DOWNSTREAM, false);
1879         }
1880     }
1881
1882     setIgnoreCompositionSelectionChange(false);
1883
1884 #if PLATFORM(IOS)        
1885     client()->stopDelayingAndCoalescingContentChangeNotifications();
1886 #endif
1887 }
1888
1889 void Editor::ignoreSpelling()
1890 {
1891     if (!client())
1892         return;
1893         
1894     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
1895     if (selectedRange)
1896         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
1897
1898     String text = selectedText();
1899     ASSERT(text.length());
1900     textChecker()->ignoreWordInSpellDocument(text);
1901 }
1902
1903 void Editor::learnSpelling()
1904 {
1905     if (!client())
1906         return;
1907         
1908     // FIXME: On Mac OS X, when use "learn" button on "Spelling and Grammar" panel, we don't call this function. It should remove misspelling markers around the learned word, see <rdar://problem/5396072>.
1909
1910     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
1911     if (selectedRange)
1912         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
1913
1914     String text = selectedText();
1915     ASSERT(text.length());
1916     textChecker()->learnWord(text);
1917 }
1918
1919 #if !PLATFORM(IOS)
1920 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
1921 {
1922     // The basic approach is to search in two phases - from the selection end to the end of the doc, and
1923     // then we wrap and search from the doc start to (approximately) where we started.
1924     
1925     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
1926     // repeated "check spelling" commands work.
1927     VisibleSelection selection(m_frame.selection().selection());
1928     RefPtr<Range> spellingSearchRange(rangeOfContents(document()));
1929
1930     bool startedWithSelection = false;
1931     if (selection.start().deprecatedNode()) {
1932         startedWithSelection = true;
1933         if (startBeforeSelection) {
1934             VisiblePosition start(selection.visibleStart());
1935             // We match AppKit's rule: Start 1 character before the selection.
1936             VisiblePosition oneBeforeStart = start.previous();
1937             setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
1938         } else
1939             setStart(spellingSearchRange.get(), selection.visibleEnd());
1940     }
1941
1942     Position position = spellingSearchRange->startPosition();
1943     if (!isEditablePosition(position)) {
1944         // This shouldn't happen in very often because the Spelling menu items aren't enabled unless the
1945         // selection is editable.
1946         // This can happen in Mail for a mix of non-editable and editable content (like Stationary), 
1947         // when spell checking the whole document before sending the message.
1948         // In that case the document might not be editable, but there are editable pockets that need to be spell checked.
1949
1950         position = VisiblePosition(firstEditablePositionAfterPositionInRoot(position, document().documentElement())).deepEquivalent();
1951         if (position.isNull())
1952             return;
1953         
1954         Position rangeCompliantPosition = position.parentAnchoredEquivalent();
1955         if (rangeCompliantPosition.deprecatedNode())
1956             spellingSearchRange->setStart(*rangeCompliantPosition.deprecatedNode(), rangeCompliantPosition.deprecatedEditingOffset(), IGNORE_EXCEPTION);
1957         startedWithSelection = false; // won't need to wrap
1958     }
1959     
1960     // topNode defines the whole range we want to operate on 
1961     auto* topNode = highestEditableRoot(position);
1962     // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
1963     if (topNode)
1964         spellingSearchRange->setEnd(*topNode, lastOffsetForEditing(*topNode), IGNORE_EXCEPTION);
1965
1966     // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
1967     // at a word boundary. Going back by one char and then forward by a word does the trick.
1968     if (startedWithSelection) {
1969         VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.get(), DOWNSTREAM).previous();
1970         if (oneBeforeStart.isNotNull())
1971             setStart(spellingSearchRange.get(), endOfWord(oneBeforeStart));
1972         // else we were already at the start of the editable node
1973     }
1974
1975     if (spellingSearchRange->collapsed())
1976         return; // nothing to search in
1977     
1978     // Get the spell checker if it is available
1979     if (!client())
1980         return;
1981         
1982     // We go to the end of our first range instead of the start of it, just to be sure
1983     // we don't get foiled by any word boundary problems at the start.  It means we might
1984     // do a tiny bit more searching.
1985     Node& searchEndNodeAfterWrap = spellingSearchRange->endContainer();
1986     int searchEndOffsetAfterWrap = spellingSearchRange->endOffset();
1987     
1988     int misspellingOffset = 0;
1989     GrammarDetail grammarDetail;
1990     int grammarPhraseOffset = 0;
1991     RefPtr<Range> grammarSearchRange;
1992     String badGrammarPhrase;
1993     String misspelledWord;
1994
1995     bool isSpelling = true;
1996     int foundOffset = 0;
1997     String foundItem;
1998     RefPtr<Range> firstMisspellingRange;
1999     if (unifiedTextCheckerEnabled()) {
2000         grammarSearchRange = spellingSearchRange->cloneRange();
2001         foundItem = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2002         if (isSpelling) {
2003             misspelledWord = foundItem;
2004             misspellingOffset = foundOffset;
2005         } else {
2006             badGrammarPhrase = foundItem;
2007             grammarPhraseOffset = foundOffset;
2008         }
2009     } else {
2010         misspelledWord = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2011
2012 #if USE(GRAMMAR_CHECKING)
2013         grammarSearchRange = spellingSearchRange->cloneRange();
2014         if (!misspelledWord.isEmpty()) {
2015             // Stop looking at start of next misspelled word
2016             CharacterIterator chars(*grammarSearchRange);
2017             chars.advance(misspellingOffset);
2018             grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION);
2019         }
2020     
2021         if (isGrammarCheckingEnabled())
2022             badGrammarPhrase = TextCheckingHelper(client(), grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2023 #endif
2024     }
2025     
2026     // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
2027     // block rather than at a selection).
2028     if (startedWithSelection && !misspelledWord && !badGrammarPhrase) {
2029         if (topNode)
2030             spellingSearchRange->setStart(*topNode, 0, IGNORE_EXCEPTION);
2031         // going until the end of the very first chunk we tested is far enough
2032         spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfterWrap, IGNORE_EXCEPTION);
2033         
2034         if (unifiedTextCheckerEnabled()) {
2035             grammarSearchRange = spellingSearchRange->cloneRange();
2036             foundItem = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2037             if (isSpelling) {
2038                 misspelledWord = foundItem;
2039                 misspellingOffset = foundOffset;
2040             } else {
2041                 badGrammarPhrase = foundItem;
2042                 grammarPhraseOffset = foundOffset;
2043             }
2044         } else {
2045             misspelledWord = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2046
2047 #if USE(GRAMMAR_CHECKING)
2048             grammarSearchRange = spellingSearchRange->cloneRange();
2049             if (!misspelledWord.isEmpty()) {
2050                 // Stop looking at start of next misspelled word
2051                 CharacterIterator chars(*grammarSearchRange);
2052                 chars.advance(misspellingOffset);
2053                 grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION);
2054             }
2055
2056             if (isGrammarCheckingEnabled())
2057                 badGrammarPhrase = TextCheckingHelper(client(), grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2058 #endif
2059         }
2060     }
2061     
2062 #if !USE(GRAMMAR_CHECKING)
2063     ASSERT(badGrammarPhrase.isEmpty());
2064     UNUSED_PARAM(grammarPhraseOffset);
2065 #else
2066     if (!badGrammarPhrase.isEmpty()) {
2067         // We found bad grammar. Since we only searched for bad grammar up to the first misspelled word, the bad grammar
2068         // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling
2069         // panel, and store a marker so we draw the green squiggle later.
2070         
2071         ASSERT(badGrammarPhrase.length() > 0);
2072         ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0);
2073         
2074         // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph
2075         RefPtr<Range> badGrammarRange = TextIterator::subrange(grammarSearchRange.get(), grammarPhraseOffset + grammarDetail.location, grammarDetail.length);
2076         m_frame.selection().setSelection(VisibleSelection(*badGrammarRange, SEL_DEFAULT_AFFINITY));
2077         m_frame.selection().revealSelection();
2078         
2079         client()->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
2080         document().markers().addMarker(badGrammarRange.get(), DocumentMarker::Grammar, grammarDetail.userDescription);
2081     } else
2082 #endif
2083     if (!misspelledWord.isEmpty()) {
2084         // We found a misspelling, but not any earlier bad grammar. Select the misspelling, update the spelling panel, and store
2085         // a marker so we draw the red squiggle later.
2086         
2087         RefPtr<Range> misspellingRange = TextIterator::subrange(spellingSearchRange.get(), misspellingOffset, misspelledWord.length());
2088         m_frame.selection().setSelection(VisibleSelection(*misspellingRange, DOWNSTREAM));
2089         m_frame.selection().revealSelection();
2090         
2091         client()->updateSpellingUIWithMisspelledWord(misspelledWord);
2092         document().markers().addMarker(misspellingRange.get(), DocumentMarker::Spelling);
2093     }
2094 }
2095 #endif // !PLATFORM(IOS)
2096
2097 String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
2098 {
2099     if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
2100         return String();
2101
2102     VisibleSelection selection = m_frame.selection().selection();
2103     if (!selection.isContentEditable() || selection.isNone())
2104         return String();
2105
2106     VisibleSelection wordSelection(selection.base());
2107     wordSelection.expandUsingGranularity(WordGranularity);
2108     RefPtr<Range> wordRange = wordSelection.toNormalizedRange();
2109
2110     // In compliance with GTK+ applications, additionally allow to provide suggestions when the current
2111     // selection exactly match the word selection.
2112     if (selection.isRange() && !areRangesEqual(wordRange.get(), selection.toNormalizedRange().get()))
2113         return String();
2114
2115     String word = wordRange->text();
2116     if (word.isEmpty() || !client())
2117         return String();
2118
2119     int wordLength = word.length();
2120     int misspellingLocation = -1;
2121     int misspellingLength = 0;
2122     textChecker()->checkSpellingOfString(word, &misspellingLocation, &misspellingLength);
2123
2124     return misspellingLength == wordLength ? word : String();
2125 }
2126
2127 String Editor::misspelledSelectionString() const
2128 {
2129     String selectedString = selectedText();
2130     int length = selectedString.length();
2131     if (!length || !client())
2132         return String();
2133
2134     int misspellingLocation = -1;
2135     int misspellingLength = 0;
2136     textChecker()->checkSpellingOfString(selectedString, &misspellingLocation, &misspellingLength);
2137     
2138     // The selection only counts as misspelled if the selected text is exactly one misspelled word
2139     if (misspellingLength != length)
2140         return String();
2141     
2142     // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
2143     // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
2144     // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling
2145     // or a grammar error.
2146     client()->updateSpellingUIWithMisspelledWord(selectedString);
2147     
2148     return selectedString;
2149 }
2150
2151 bool Editor::isSelectionUngrammatical()
2152 {
2153 #if USE(GRAMMAR_CHECKING)
2154     RefPtr<Range> range = m_frame.selection().toNormalizedRange();
2155     if (!range)
2156         return false;
2157     return TextCheckingHelper(client(), range).isUngrammatical();
2158 #else
2159     return false;
2160 #endif
2161 }
2162
2163 Vector<String> Editor::guessesForMisspelledWord(const String& word) const
2164 {
2165     ASSERT(word.length());
2166
2167     Vector<String> guesses;
2168     if (client())
2169         textChecker()->getGuessesForWord(word, String(), m_frame.selection().selection(), guesses);
2170     return guesses;
2171 }
2172
2173 Vector<String> Editor::guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical)
2174 {
2175     if (unifiedTextCheckerEnabled()) {
2176         RefPtr<Range> range;
2177         VisibleSelection selection = m_frame.selection().selection();
2178         if (selection.isCaret() && behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
2179             VisibleSelection wordSelection = VisibleSelection(selection.base());
2180             wordSelection.expandUsingGranularity(WordGranularity);
2181             range = wordSelection.toNormalizedRange();
2182         } else
2183             range = selection.toNormalizedRange();
2184         if (!range)
2185             return Vector<String>();
2186         return TextCheckingHelper(client(), range).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);
2187     }
2188
2189     String misspelledWord = behavior().shouldAllowSpellingSuggestionsWithoutSelection() ? misspelledWordAtCaretOrRange(document().focusedElement()) : misspelledSelectionString();
2190     misspelled = !misspelledWord.isEmpty();
2191     // Only unified text checker supports guesses for ungrammatical phrases.
2192     ungrammatical = false;
2193
2194     if (misspelled)
2195         return guessesForMisspelledWord(misspelledWord);
2196     return Vector<String>();
2197 }
2198
2199 void Editor::showSpellingGuessPanel()
2200 {
2201     if (!client()) {
2202         LOG_ERROR("No NSSpellChecker");
2203         return;
2204     }
2205
2206     if (client()->spellingUIIsShowing()) {
2207         client()->showSpellingUI(false);
2208         return;
2209     }
2210
2211 #if !PLATFORM(IOS)
2212     advanceToNextMisspelling(true);
2213 #endif
2214     client()->showSpellingUI(true);
2215 }
2216
2217 bool Editor::spellingPanelIsShowing()
2218 {
2219     if (!client())
2220         return false;
2221     return client()->spellingUIIsShowing();
2222 }
2223
2224 void Editor::clearMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
2225 {
2226     RefPtr<Range> selectedRange = movingSelection.toNormalizedRange();
2227     if (selectedRange) {
2228         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
2229         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Grammar);
2230     }
2231 }
2232
2233 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
2234 {
2235     markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled(), movingSelection);
2236 }
2237
2238 void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement)
2239 {
2240 #if PLATFORM(IOS)
2241     UNUSED_PARAM(selectionAfterTyping);
2242     UNUSED_PARAM(doReplacement);
2243     TextCheckingTypeMask textCheckingOptions = 0;
2244     if (isContinuousSpellCheckingEnabled())
2245         textCheckingOptions |= TextCheckingTypeSpelling;
2246     if (!(textCheckingOptions & TextCheckingTypeSpelling))
2247         return;
2248
2249     VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
2250     markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
2251 #else
2252 #if !USE(AUTOMATIC_TEXT_REPLACEMENT)
2253     UNUSED_PARAM(doReplacement);
2254 #endif
2255
2256     if (unifiedTextCheckerEnabled()) {
2257         m_alternativeTextController->applyPendingCorrection(selectionAfterTyping);
2258
2259         TextCheckingTypeMask textCheckingOptions = 0;
2260
2261         if (isContinuousSpellCheckingEnabled())
2262             textCheckingOptions |= TextCheckingTypeSpelling;
2263
2264 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2265         if (doReplacement
2266             && (isAutomaticQuoteSubstitutionEnabled()
2267                 || isAutomaticLinkDetectionEnabled()
2268                 || isAutomaticDashSubstitutionEnabled()
2269                 || isAutomaticTextReplacementEnabled()
2270                 || ((textCheckingOptions & TextCheckingTypeSpelling) && isAutomaticSpellingCorrectionEnabled())))
2271             textCheckingOptions |= TextCheckingTypeReplacement;
2272 #endif
2273         if (!(textCheckingOptions & (TextCheckingTypeSpelling | TextCheckingTypeReplacement)))
2274             return;
2275
2276         if (isGrammarCheckingEnabled())
2277             textCheckingOptions |= TextCheckingTypeGrammar;
2278
2279         VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
2280         if (textCheckingOptions & TextCheckingTypeGrammar) {
2281             VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart));
2282             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), selectedSentence.toNormalizedRange().get());
2283         } else
2284             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
2285         return;
2286     }
2287
2288     if (!isContinuousSpellCheckingEnabled())
2289         return;
2290
2291     // Check spelling of one word
2292     RefPtr<Range> misspellingRange;
2293     markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)), misspellingRange);
2294
2295     // Autocorrect the misspelled word.
2296     if (!misspellingRange)
2297         return;
2298     
2299     // Get the misspelled word.
2300     const String misspelledWord = plainText(misspellingRange.get());
2301     String autocorrectedString = textChecker()->getAutoCorrectSuggestionForMisspelledWord(misspelledWord);
2302
2303     // If autocorrected word is non empty, replace the misspelled word by this word.
2304     if (!autocorrectedString.isEmpty()) {
2305         VisibleSelection newSelection(*misspellingRange, DOWNSTREAM);
2306         if (newSelection != m_frame.selection().selection()) {
2307             if (!m_frame.selection().shouldChangeSelection(newSelection))
2308                 return;
2309             m_frame.selection().setSelection(newSelection);
2310         }
2311
2312         if (!m_frame.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertActionTyped))
2313             return;
2314         m_frame.editor().replaceSelectionWithText(autocorrectedString, false, false, EditActionInsert);
2315
2316         // Reset the charet one character further.
2317         m_frame.selection().moveTo(m_frame.selection().selection().end());
2318         m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2319     }
2320
2321     if (!isGrammarCheckingEnabled())
2322         return;
2323     
2324     // Check grammar of entire sentence
2325     markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart)));
2326 #endif
2327 }
2328     
2329 void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
2330 {
2331 #if !PLATFORM(IOS)
2332     // This function is called with a selection already expanded to word boundaries.
2333     // Might be nice to assert that here.
2334     
2335     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
2336     // grammar checking can only be on if spell checking is also on.
2337     if (!isContinuousSpellCheckingEnabled())
2338         return;
2339     
2340     RefPtr<Range> searchRange(selection.toNormalizedRange());
2341     if (!searchRange)
2342         return;
2343     
2344     // If we're not in an editable node, bail.
2345     Node& editableNode = searchRange->startContainer();
2346     if (!editableNode.hasEditableStyle())
2347         return;
2348
2349     if (!isSpellCheckingEnabledFor(&editableNode))
2350         return;
2351
2352     // Get the spell checker if it is available
2353     if (!client())
2354         return;
2355     
2356     TextCheckingHelper checker(client(), searchRange);
2357     if (checkSpelling)
2358         checker.markAllMisspellings(firstMisspellingRange);
2359     else {
2360 #if USE(GRAMMAR_CHECKING)
2361         if (isGrammarCheckingEnabled())
2362             checker.markAllBadGrammar();
2363 #else
2364         ASSERT_NOT_REACHED();
2365 #endif
2366     }    
2367 #else
2368         UNUSED_PARAM(selection);
2369         UNUSED_PARAM(checkSpelling);
2370         UNUSED_PARAM(firstMisspellingRange);
2371 #endif // !PLATFORM(IOS)
2372 }
2373
2374 bool Editor::isSpellCheckingEnabledFor(Node* node) const
2375 {
2376     if (!node)
2377         return false;
2378     Element* element = is<Element>(*node) ? downcast<Element>(node) : node->parentElement();
2379     if (!element)
2380         return false;
2381     if (element->isInUserAgentShadowTree()) {
2382         if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(firstPositionInOrBeforeNode(element)))
2383             return textControl->isSpellCheckingEnabled();
2384     }
2385     return element->isSpellCheckingEnabled();
2386 }
2387
2388 bool Editor::isSpellCheckingEnabledInFocusedNode() const
2389 {
2390     return isSpellCheckingEnabledFor(m_frame.selection().selection().start().deprecatedNode());
2391 }
2392
2393 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
2394 {
2395     markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
2396 }
2397     
2398 void Editor::markBadGrammar(const VisibleSelection& selection)
2399 {
2400 #if USE(GRAMMAR_CHECKING)
2401     RefPtr<Range> firstMisspellingRange;
2402     markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
2403 #else
2404     ASSERT_NOT_REACHED();
2405 #endif
2406 }
2407
2408 void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, Range* spellingRange, Range* grammarRange)
2409 {
2410     ASSERT(unifiedTextCheckerEnabled());
2411
2412     // There shouldn't be pending autocorrection at this moment.
2413     ASSERT(!m_alternativeTextController->hasPendingCorrection());
2414
2415     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
2416     bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
2417
2418     // This function is called with selections already expanded to word boundaries.
2419     if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange))
2420         return;
2421
2422     // If we're not in an editable node, bail.
2423     Node& editableNode = spellingRange->startContainer();
2424     if (!editableNode.hasEditableStyle())
2425         return;
2426
2427     if (!isSpellCheckingEnabledFor(&editableNode))
2428         return;
2429
2430     Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange;
2431     TextCheckingParagraph paragraphToCheck(rangeToCheck);
2432     if (paragraphToCheck.isEmpty())
2433         return;
2434     RefPtr<Range> paragraphRange = paragraphToCheck.paragraphRange();
2435
2436     bool asynchronous = m_frame.settings().asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel;
2437
2438     // In asynchronous mode, we intentionally check paragraph-wide sentence.
2439     auto request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessIncremental, asynchronous ? paragraphRange : rangeToCheck, paragraphRange);
2440
2441     if (asynchronous) {
2442         m_spellChecker->requestCheckingFor(WTFMove(request));
2443         return;
2444     }
2445
2446     Vector<TextCheckingResult> results;
2447     checkTextOfParagraph(*textChecker(), paragraphToCheck.text(), resolveTextCheckingTypeMask(textCheckingOptions), results, m_frame.selection().selection());
2448     markAndReplaceFor(WTFMove(request), results);
2449 }
2450
2451 static bool isAutomaticTextReplacementType(TextCheckingType type)
2452 {
2453     switch (type) {
2454     case TextCheckingTypeNone:
2455     case TextCheckingTypeSpelling:
2456     case TextCheckingTypeGrammar:
2457         return false;
2458     case TextCheckingTypeLink:
2459     case TextCheckingTypeQuote:
2460     case TextCheckingTypeDash:
2461     case TextCheckingTypeReplacement:
2462     case TextCheckingTypeCorrection:
2463     case TextCheckingTypeShowCorrectionPanel:
2464         return true;
2465     }
2466     ASSERT_NOT_REACHED();
2467     return false;
2468 }
2469
2470 static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingParagraph& paragraph, PassRefPtr<Range> rangeToReplace, const String& replacement, int resultLocation, int resultLength)
2471 {
2472     ContainerNode* scope = downcast<ContainerNode>(paragraph.paragraphRange()->startContainer().rootNode());
2473
2474     size_t paragraphLocation;
2475     size_t paragraphLength;
2476     TextIterator::getLocationAndLengthFromRange(scope, paragraph.paragraphRange().get(), paragraphLocation, paragraphLength);
2477
2478     applyCommand(SpellingCorrectionCommand::create(rangeToReplace, replacement));
2479
2480     // TextCheckingParagraph may be orphaned after SpellingCorrectionCommand mutated DOM.
2481     // See <rdar://10305315>, http://webkit.org/b/89526.
2482
2483     RefPtr<Range> newParagraphRange = TextIterator::rangeFromLocationAndLength(scope, paragraphLocation, paragraphLength + replacement.length() - resultLength);
2484
2485     paragraph = TextCheckingParagraph(TextIterator::subrange(newParagraphRange.get(), resultLocation, replacement.length()), newParagraphRange);
2486 }
2487
2488 void Editor::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, const Vector<TextCheckingResult>& results)
2489 {
2490     ASSERT(request);
2491
2492     TextCheckingTypeMask textCheckingOptions = request->data().mask();
2493     TextCheckingParagraph paragraph(request->checkingRange(), request->paragraphRange());
2494
2495     const bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
2496     const bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
2497     const bool shouldMarkLink = textCheckingOptions & TextCheckingTypeLink;
2498     const bool shouldPerformReplacement = textCheckingOptions & (TextCheckingTypeQuote | TextCheckingTypeDash | TextCheckingTypeReplacement);
2499     const bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
2500     const bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
2501 #if !USE(AUTOCORRECTION_PANEL)
2502     ASSERT(!shouldShowCorrectionPanel);
2503 #endif
2504
2505     // Expand the range to encompass entire paragraphs, since text checking needs that much context.
2506     int selectionOffset = 0;
2507     bool useAmbiguousBoundaryOffset = false;
2508     bool selectionChanged = false;
2509     bool restoreSelectionAfterChange = false;
2510     bool adjustSelectionForParagraphBoundaries = false;
2511
2512     if (shouldPerformReplacement || shouldMarkSpelling || shouldCheckForCorrection) {
2513         if (m_frame.selection().selection().selectionType() == VisibleSelection::CaretSelection) {
2514             // Attempt to save the caret position so we can restore it later if needed
2515             Position caretPosition = m_frame.selection().selection().end();
2516             selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPTION);
2517             restoreSelectionAfterChange = true;
2518             if (selectionOffset > 0 && (selectionOffset > paragraph.textLength() || paragraph.textCharAt(selectionOffset - 1) == newlineCharacter))
2519                 adjustSelectionForParagraphBoundaries = true;
2520             if (selectionOffset > 0 && selectionOffset <= paragraph.textLength() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(selectionOffset - 1)))
2521                 useAmbiguousBoundaryOffset = true;
2522         }
2523     }
2524
2525     int offsetDueToReplacement = 0;
2526
2527     for (unsigned i = 0; i < results.size(); i++) {
2528         const int spellingRangeEndOffset = paragraph.checkingEnd() + offsetDueToReplacement;
2529         const TextCheckingType resultType = results[i].type;
2530         const int resultLocation = results[i].location + offsetDueToReplacement;
2531         const int resultLength = results[i].length;
2532         const int resultEndLocation = resultLocation + resultLength;
2533         const String& replacement = results[i].replacement;
2534         const bool resultEndsAtAmbiguousBoundary = useAmbiguousBoundaryOffset && selectionOffset - 1 <= resultEndLocation;
2535
2536         // Only mark misspelling if:
2537         // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false.
2538         // 2. Result falls within spellingRange.
2539         // 3. The word in question doesn't end at an ambiguous boundary. For instance, we would not mark
2540         //    "wouldn'" as misspelled right after apostrophe is typed.
2541         if (shouldMarkSpelling && !shouldShowCorrectionPanel && resultType == TextCheckingTypeSpelling
2542             && resultLocation >= paragraph.checkingStart() && resultEndLocation <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
2543             ASSERT(resultLength > 0 && resultLocation >= 0);
2544             RefPtr<Range> misspellingRange = paragraph.subrange(resultLocation, resultLength);
2545             if (!m_alternativeTextController->isSpellingMarkerAllowed(misspellingRange))
2546                 continue;
2547             misspellingRange->startContainer().document().markers().addMarker(misspellingRange.get(), DocumentMarker::Spelling, replacement);
2548         } else if (shouldMarkGrammar && resultType == TextCheckingTypeGrammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
2549             ASSERT(resultLength > 0 && resultLocation >= 0);
2550             for (auto& detail : results[i].details) {
2551                 ASSERT(detail.length > 0 && detail.location >= 0);
2552                 if (paragraph.checkingRangeCovers(resultLocation + detail.location, detail.length)) {
2553                     RefPtr<Range> badGrammarRange = paragraph.subrange(resultLocation + detail.location, detail.length);
2554                     badGrammarRange->startContainer().document().markers().addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail.userDescription);
2555                 }
2556             }
2557         } else if (resultEndLocation <= spellingRangeEndOffset && resultEndLocation >= paragraph.checkingStart()
2558             && isAutomaticTextReplacementType(resultType)) {
2559             // In this case the result range just has to touch the spelling range, so we can handle replacing non-word text such as punctuation.
2560             ASSERT(resultLength > 0 && resultLocation >= 0);
2561
2562             if (shouldShowCorrectionPanel && (resultEndLocation < spellingRangeEndOffset
2563                 || !(resultType & (TextCheckingTypeReplacement | TextCheckingTypeCorrection))))
2564                 continue;
2565
2566             // Apply replacement if:
2567             // 1. The replacement length is non-zero.
2568             // 2. The result doesn't end at an ambiguous boundary.
2569             //    (FIXME: this is required until 6853027 is fixed and text checking can do this for us
2570             bool doReplacement = replacement.length() > 0 && !resultEndsAtAmbiguousBoundary;
2571             RefPtr<Range> rangeToReplace = paragraph.subrange(resultLocation, resultLength);
2572
2573             // adding links should be done only immediately after they are typed
2574             if (resultType == TextCheckingTypeLink && selectionOffset != resultEndLocation + 1)
2575                 continue;
2576
2577             if (!(shouldPerformReplacement || shouldCheckForCorrection || shouldMarkLink) || !doReplacement)
2578                 continue;
2579
2580             String replacedString = plainText(rangeToReplace.get());
2581             const bool existingMarkersPermitReplacement = m_alternativeTextController->processMarkersOnTextToBeReplacedByResult(&results[i], rangeToReplace.get(), replacedString);
2582             if (!existingMarkersPermitReplacement)
2583                 continue;
2584
2585             if (shouldShowCorrectionPanel) {
2586                 if (resultEndLocation == spellingRangeEndOffset) {
2587                     // We only show the correction panel on the last word.
2588                     m_alternativeTextController->show(rangeToReplace, replacement);
2589                     break;
2590                 }
2591                 // If this function is called for showing correction panel, we ignore other correction or replacement.
2592                 continue;
2593             }
2594
2595             VisibleSelection selectionToReplace(*rangeToReplace, DOWNSTREAM);
2596             if (selectionToReplace != m_frame.selection().selection()) {
2597                 if (!m_frame.selection().shouldChangeSelection(selectionToReplace))
2598                     continue;
2599             }
2600
2601             if (resultType == TextCheckingTypeLink) {
2602                 m_frame.selection().setSelection(selectionToReplace);
2603                 selectionChanged = true;
2604                 restoreSelectionAfterChange = false;
2605                 if (canEditRichly())
2606                     applyCommand(CreateLinkCommand::create(document(), replacement));
2607             } else if (canEdit() && shouldInsertText(replacement, rangeToReplace.get(), EditorInsertActionTyped)) {
2608                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, resultLocation, resultLength);
2609
2610                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
2611                     if (Element* root = m_frame.selection().selection().rootEditableElement())
2612                         cache->postNotification(root, AXObjectCache::AXAutocorrectionOccured);
2613                 }
2614
2615                 // Skip all other results for the replaced text.
2616                 while (i + 1 < results.size() && results[i + 1].location + offsetDueToReplacement <= resultLocation)
2617                     i++;
2618
2619                 selectionChanged = true;
2620                 offsetDueToReplacement += replacement.length() - resultLength;
2621                 if (resultLocation < selectionOffset)
2622                     selectionOffset += replacement.length() - resultLength;
2623
2624                 // Add a marker so that corrections can easily be undone and won't be re-corrected.
2625                 if (resultType == TextCheckingTypeCorrection)
2626                     m_alternativeTextController->markCorrection(paragraph.subrange(resultLocation, replacement.length()), replacedString);
2627             }
2628         }
2629     }
2630
2631     if (selectionChanged) {
2632         TextCheckingParagraph extendedParagraph(paragraph);
2633         // Restore the caret position if we have made any replacements
2634         extendedParagraph.expandRangeToNextEnd();
2635         if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffset <= extendedParagraph.rangeLength()) {
2636             RefPtr<Range> selectionRange = extendedParagraph.subrange(0, selectionOffset);
2637             m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
2638             if (adjustSelectionForParagraphBoundaries)
2639                 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2640         } else {
2641             // If this fails for any reason, the fallback is to go one position beyond the last replacement
2642             m_frame.selection().moveTo(m_frame.selection().selection().end());
2643             m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2644         }
2645     }
2646 }
2647
2648 void Editor::changeBackToReplacedString(const String& replacedString)
2649 {
2650 #if !PLATFORM(IOS)
2651     ASSERT(unifiedTextCheckerEnabled());
2652
2653     if (replacedString.isEmpty())
2654         return;
2655
2656     RefPtr<Range> selection = selectedRange();
2657     if (!shouldInsertText(replacedString, selection.get(), EditorInsertActionPasted))
2658         return;
2659     
2660     m_alternativeTextController->recordAutocorrectionResponseReversed(replacedString, selection);
2661     TextCheckingParagraph paragraph(selection);
2662     replaceSelectionWithText(replacedString, false, false, EditActionInsert);
2663     RefPtr<Range> changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
2664     changedRange->startContainer().document().markers().addMarker(changedRange.get(), DocumentMarker::Replacement, String());
2665     m_alternativeTextController->markReversed(changedRange.get());
2666 #else
2667     ASSERT_NOT_REACHED();
2668     UNUSED_PARAM(replacedString);
2669 #endif // !PLATFORM(IOS)
2670 }
2671
2672
2673 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection)
2674 {
2675     if (unifiedTextCheckerEnabled()) {
2676         if (!isContinuousSpellCheckingEnabled())
2677             return;
2678
2679         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
2680         TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling;
2681         if (markGrammar && isGrammarCheckingEnabled())
2682             textCheckingOptions |= TextCheckingTypeGrammar;
2683         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedRange().get(), grammarSelection.toNormalizedRange().get());
2684         return;
2685     }
2686
2687     RefPtr<Range> firstMisspellingRange;
2688     markMisspellings(spellingSelection, firstMisspellingRange);
2689     if (markGrammar)
2690         markBadGrammar(grammarSelection);
2691 }
2692
2693 void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
2694 {
2695     m_alternativeTextController->respondToUnappliedSpellCorrection(selectionOfCorrected, corrected, correction);
2696 }
2697
2698 void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
2699 {
2700     if (!document().markers().hasMarkers())
2701         return;
2702
2703     if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)))
2704         return;
2705
2706     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
2707     // several scenarios:
2708     // 1. Insert in the middle of a word.
2709     // 2. Appending non whitespace at the beginning of word.
2710     // 3. Appending non whitespace at the end of word.
2711     // Note that, appending only whitespaces at the beginning or end of word won't change the word, so we don't need to
2712     // remove the markers on that word.
2713     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
2714     // selection, and remove words between the selection boundaries.
2715     //
2716     VisiblePosition startOfSelection = m_frame.selection().selection().start();
2717     VisiblePosition endOfSelection = m_frame.selection().selection().end();
2718     if (startOfSelection.isNull())
2719         return;
2720     // First word is the word that ends after or on the start of selection.
2721     VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfOnBoundary);
2722     VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBoundary);
2723     // Last word is the word that begins before or on the end of selection
2724     VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnBoundary);
2725     VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBoundary);
2726
2727     if (startOfFirstWord.isNull()) {
2728         startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary);
2729         endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary);
2730     }
2731     
2732     if (endOfLastWord.isNull()) {
2733         startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary);
2734         endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary);
2735     }
2736
2737     // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the start of selection,
2738     // we choose next word as the first word.
2739     if (doNotRemoveIfSelectionAtWordBoundary && endOfFirstWord == startOfSelection) {
2740         startOfFirstWord = nextWordPosition(startOfFirstWord);
2741         endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary);
2742         if (startOfFirstWord == endOfSelection)
2743             return;
2744     }
2745
2746     // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at the end of selection,
2747     // we choose previous word as the last word.
2748     if (doNotRemoveIfSelectionAtWordBoundary && startOfLastWord == endOfSelection) {
2749         startOfLastWord = previousWordPosition(startOfLastWord);
2750         endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary);
2751         if (endOfLastWord == startOfSelection)
2752             return;
2753     }
2754
2755     if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull())
2756         return;
2757
2758     // Now we remove markers on everything between startOfFirstWord and endOfLastWord.
2759     // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the
2760     // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant
2761     // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde,
2762     // we would like to remove the marker from word "avant" and whitespace as well. So we need to get the continous range of
2763     // of marker that contains the word in question, and remove marker on that whole range.
2764     RefPtr<Range> wordRange = Range::create(document(), startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
2765
2766     Vector<RenderedDocumentMarker*> markers = document().markers().markersInRange(wordRange.get(), DocumentMarker::DictationAlternatives);
2767     for (auto* marker : markers)
2768         m_alternativeTextController->removeDictationAlternativesForMarker(marker);
2769
2770 #if PLATFORM(IOS)
2771     document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::CorrectionIndicator | DocumentMarker::SpellCheckingExemption | DocumentMarker::DictationAlternatives | DocumentMarker::DictationPhraseWithAlternatives, DocumentMarkerController::RemovePartiallyOverlappingMarker);
2772 #else
2773     document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::Grammar | DocumentMarker::CorrectionIndicator | DocumentMarker::SpellCheckingExemption | DocumentMarker::DictationAlternatives, DocumentMarkerController::RemovePartiallyOverlappingMarker);
2774 #endif
2775     document().markers().clearDescriptionOnMarkersIntersectingRange(wordRange.get(), DocumentMarker::Replacement);
2776 }
2777
2778 void Editor::deletedAutocorrectionAtPosition(const Position& position, const String& originalString)
2779 {
2780     m_alternativeTextController->deletedAutocorrectionAtPosition(position, originalString);
2781 }
2782
2783 PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
2784 {
2785     Document* document = m_frame.documentAtPoint(windowPoint);
2786     if (!document)
2787         return 0;
2788     
2789     Frame* frame = document->frame();
2790     ASSERT(frame);
2791     FrameView* frameView = frame->view();
2792     if (!frameView)
2793         return 0;
2794     IntPoint framePoint = frameView->windowToContents(windowPoint);
2795     VisibleSelection selection(frame->visiblePositionForPoint(framePoint));
2796
2797     return selection.toNormalizedRange();
2798 }
2799
2800 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2801 {
2802     if (m_ignoreCompositionSelectionChange)
2803         return;
2804
2805 #if PLATFORM(IOS)
2806     SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
2807 #else
2808     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
2809 #endif
2810
2811     m_frame.selection().revealSelection(revealMode, alignment, revealExtentOption);
2812 }
2813
2814 void Editor::setIgnoreCompositionSelectionChange(bool ignore, RevealSelection shouldRevealExistingSelection)
2815 {
2816     if (m_ignoreCompositionSelectionChange == ignore)
2817         return;
2818
2819     m_ignoreCompositionSelectionChange = ignore;
2820 #if PLATFORM(IOS)
2821     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
2822     if (!ignore)
2823         respondToChangedSelection(m_frame.selection().selection(), 0);
2824 #endif
2825     if (!ignore && shouldRevealExistingSelection == RevealSelection::Yes)
2826         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
2827 }
2828
2829 RefPtr<Range> Editor::compositionRange() const
2830 {
2831     if (!m_compositionNode)
2832         return nullptr;
2833     unsigned length = m_compositionNode->length();
2834     unsigned start = std::min(m_compositionStart, length);
2835     unsigned end = std::min(std::max(start, m_compositionEnd), length);
2836     if (start >= end)
2837         return nullptr;
2838     return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
2839 }
2840
2841 bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
2842 {
2843     if (!m_compositionNode)
2844         return false;
2845     const VisibleSelection& selection = m_frame.selection().selection();
2846     Position start = selection.start();
2847     if (start.deprecatedNode() != m_compositionNode)
2848         return false;
2849     Position end = selection.end();
2850     if (end.deprecatedNode() != m_compositionNode)
2851         return false;
2852
2853     if (static_cast<unsigned>(start.deprecatedEditingOffset()) < m_compositionStart)
2854         return false;
2855     if (static_cast<unsigned>(end.deprecatedEditingOffset()) > m_compositionEnd)
2856         return false;
2857
2858     selectionStart = start.deprecatedEditingOffset() - m_compositionStart;
2859     selectionEnd = start.deprecatedEditingOffset() - m_compositionEnd;
2860     return true;
2861 }
2862
2863 void Editor::transpose()
2864 {
2865     if (!canEdit())
2866         return;
2867
2868     VisibleSelection selection = m_frame.selection().selection();
2869     if (!selection.isCaret())
2870         return;
2871
2872     // Make a selection that goes back one character and forward two characters.
2873     VisiblePosition caret = selection.visibleStart();
2874     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
2875     VisiblePosition previous = next.previous();
2876     if (next == previous)
2877         return;
2878     previous = previous.previous();
2879     if (!inSameParagraph(next, previous))
2880         return;
2881     RefPtr<Range> range = makeRange(previous, next);
2882     if (!range)
2883         return;
2884     VisibleSelection newSelection(*range, DOWNSTREAM);
2885
2886     // Transpose the two characters.
2887     String text = plainText(range.get());
2888     if (text.length() != 2)
2889         return;
2890     String transposed = text.right(1) + text.left(1);
2891
2892     // Select the two characters.
2893     if (newSelection != m_frame.selection().selection()) {
2894         if (!m_frame.selection().shouldChangeSelection(newSelection))
2895             return;
2896         m_frame.selection().setSelection(newSelection);
2897     }
2898
2899     // Insert the transposed characters.
2900     if (!shouldInsertText(transposed, range.get(), EditorInsertActionTyped))
2901         return;
2902     replaceSelectionWithText(transposed, false, false, EditActionInsert);
2903 }
2904
2905 void Editor::addRangeToKillRing(const Range& range, KillRingInsertionMode mode)
2906 {
2907     addTextToKillRing(plainText(&range), mode);
2908 }
2909
2910 void Editor::addTextToKillRing(const String& text, KillRingInsertionMode mode)
2911 {
2912     if (m_shouldStartNewKillRingSequence)
2913         killRing().startNewSequence();
2914
2915     m_shouldStartNewKillRingSequence = false;
2916
2917     // If the kill was from a backwards motion, prepend to the kill ring.
2918     // This will ensure that alternating forward and backward kills will
2919     // build up the original string in the kill ring without permuting it.
2920     switch (mode) {
2921     case KillRingInsertionMode::PrependText:
2922         killRing().prepend(text);
2923         break;
2924     case KillRingInsertionMode::AppendText:
2925         killRing().append(text);
2926         break;
2927     }
2928 }
2929
2930 void Editor::startAlternativeTextUITimer()
2931 {
2932     m_alternativeTextController->startAlternativeTextUITimer(AlternativeTextTypeCorrection);
2933 }
2934
2935 void Editor::handleAlternativeTextUIResult(const String& correction)
2936 {
2937     m_alternativeTextController->handleAlternativeTextUIResult(correction);
2938 }
2939
2940
2941 void Editor::dismissCorrectionPanelAsIgnored()
2942 {
2943     m_alternativeTextController->dismiss(ReasonForDismissingAlternativeTextIgnored);
2944 }
2945
2946 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions options)
2947 {
2948     // If the new selection is orphaned, then don't update the selection.
2949     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
2950         return;
2951
2952     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
2953     // because there is work that it must do in this situation.
2954     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
2955     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
2956     bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
2957     if (selectionDidNotChangeDOMPosition || m_frame.selection().shouldChangeSelection(newSelection))
2958         m_frame.selection().setSelection(newSelection, options);
2959
2960     // Some editing operations change the selection visually without affecting its position within the DOM.
2961     // For example when you press return in the following (the caret is marked by ^):
2962     // <div contentEditable="true"><div>^Hello</div></div>
2963     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
2964     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
2965     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
2966     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
2967 #if PLATFORM(IOS)
2968     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830>
2969     if (m_ignoreCompositionSelectionChange)
2970         return;
2971 #endif
2972     if (selectionDidNotChangeDOMPosition && client())
2973         client()->respondToChangedSelection(&m_frame);
2974 }
2975
2976 String Editor::selectedText() const
2977 {
2978     return selectedText(TextIteratorDefaultBehavior);
2979 }
2980
2981 String Editor::selectedTextForDataTransfer() const
2982 {
2983     if (m_frame.settings().selectionIncludesAltImageText())
2984         return selectedText(TextIteratorEmitsImageAltText);
2985     return selectedText();
2986 }
2987
2988 String Editor::selectedText(TextIteratorBehavior behavior) const
2989 {
2990     // We remove '\0' characters because they are not visibly rendered to the user.
2991     return plainText(m_frame.selection().toNormalizedRange().get(), behavior).replaceWithLiteral('\0', "");
2992 }
2993
2994 static inline void collapseCaretWidth(IntRect& rect)
2995 {
2996     // FIXME: Width adjustment doesn't work for rotated text.
2997     if (rect.width() == caretWidth)
2998         rect.setWidth(0);
2999     else if (rect.height() == caretWidth)
3000         rect.setHeight(0);
3001 }
3002
3003 IntRect Editor::firstRectForRange(Range* range) const
3004 {
3005     VisiblePosition startVisiblePosition(range->startPosition(), DOWNSTREAM);
3006
3007     if (range->collapsed()) {
3008         // FIXME: Getting caret rect and removing caret width is a very roundabout way to get collapsed range location.
3009         // In particular, width adjustment doesn't work for rotated text.
3010         IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect();
3011         collapseCaretWidth(startCaretRect);
3012         return startCaretRect;
3013     }
3014
3015     VisiblePosition endVisiblePosition(range->endPosition(), UPSTREAM);
3016
3017     if (inSameLine(startVisiblePosition, endVisiblePosition))
3018         return enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(range));
3019
3020     LayoutUnit extraWidthToEndOfLine = 0;
3021     IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect(&extraWidthToEndOfLine);
3022     if (startCaretRect == IntRect())
3023         return IntRect();
3024
3025     // When start and end aren't on the same line, we want to go from start to the end of its line.
3026     bool textIsHorizontal = startCaretRect.width() == caretWidth;
3027     return textIsHorizontal ?
3028         IntRect(startCaretRect.x(),
3029             startCaretRect.y(),
3030             startCaretRect.width() + extraWidthToEndOfLine,
3031             startCaretRect.height()) :
3032         IntRect(startCaretRect.x(),
3033             startCaretRect.y(),
3034             startCaretRect.width(),
3035             startCaretRect.height() + extraWidthToEndOfLine);
3036 }
3037
3038 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
3039 {
3040 #if PLATFORM(IOS)
3041     if (m_frame.selectionChangeCallbacksDisabled())
3042         return true;
3043 #endif
3044     return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting);
3045 }
3046
3047 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
3048 {
3049     if (style.isEmpty()) {
3050         m_frame.selection().clearTypingStyle();
3051         return;
3052     }
3053
3054     // Calculate the current typing style.
3055     RefPtr<EditingStyle> typingStyle;
3056     if (auto existingTypingStyle = m_frame.selection().typingStyle())
3057         typingStyle = existingTypingStyle->copy();
3058     else
3059         typingStyle = EditingStyle::create();
3060     typingStyle->overrideTypingStyleAt(style, m_frame.selection().selection().visibleStart().deepEquivalent());
3061
3062     // Handle block styles, substracting these from the typing style.
3063     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
3064     if (!blockStyle->isEmpty())
3065         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
3066
3067     // Set the remaining style as the typing style.
3068     m_frame.selection().setTypingStyle(typingStyle);
3069 }
3070
3071 void Editor::computeAndSetTypingStyle(StyleProperties& properties, EditAction editingAction)
3072 {
3073     return computeAndSetTypingStyle(EditingStyle::create(&properties), editingAction);
3074 }
3075
3076 void Editor::textFieldDidBeginEditing(Element* e)
3077 {
3078     if (client())
3079         client()->textFieldDidBeginEditing(e);
3080 }
3081
3082 void Editor::textFieldDidEndEditing(Element* e)
3083 {
3084     dismissCorrectionPanelAsIgnored();
3085     if (client())
3086         client()->textFieldDidEndEditing(e);
3087 }
3088
3089 void Editor::textDidChangeInTextField(Element* e)
3090 {
3091     if (client())
3092         client()->textDidChangeInTextField(e);
3093 }
3094
3095 bool Editor::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
3096 {
3097     if (client())
3098         return client()->doTextFieldCommandFromEvent(e, ke);
3099
3100     return false;
3101 }
3102
3103 void Editor::textWillBeDeletedInTextField(Element* input)
3104 {
3105     if (client())
3106         client()->textWillBeDeletedInTextField(input);
3107 }
3108
3109 void Editor::textDidChangeInTextArea(Element* e)
3110 {
3111     if (client())
3112         client()->textDidChangeInTextArea(e);
3113 }
3114
3115 void Editor::applyEditingStyleToBodyElement() const
3116 {
3117     auto collection = document().getElementsByTagName(HTMLNames::bodyTag.localName());
3118     unsigned length = collection->length();
3119     for (unsigned i = 0; i < length; ++i)
3120         applyEditingStyleToElement(collection->item(i));
3121 }
3122
3123 void Editor::applyEditingStyleToElement(Element* element) const
3124 {
3125     ASSERT(!element || is<StyledElement>(*element));
3126     if (!is<StyledElement>(element))
3127         return;
3128
3129     // Mutate using the CSSOM wrapper so we get the same event behavior as a script.
3130     CSSStyleDeclaration* style = downcast<StyledElement>(*element).cssomStyle();
3131     style->setPropertyInternal(CSSPropertyWordWrap, "break-word", false, IGNORE_EXCEPTION);
3132     style->setPropertyInternal(CSSPropertyWebkitNbspMode, "space", false, IGNORE_EXCEPTION);
3133     style->setPropertyInternal(CSSPropertyWebkitLineBreak, "after-white-space", false, IGNORE_EXCEPTION);
3134 }
3135
3136 bool Editor::findString(const String& target, FindOptions options)
3137 {
3138     VisibleSelection selection = m_frame.selection().selection();
3139
3140     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
3141
3142     if (!resultRange)
3143         return false;
3144
3145     m_frame.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
3146
3147     if (!(options & DoNotRevealSelection))
3148         m_frame.selection().revealSelection();
3149
3150     return true;
3151 }
3152
3153 RefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
3154 {
3155     RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
3156     if (!nextMatch)
3157         return nullptr;
3158
3159     nextMatch->firstNode()->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, nextMatch->absoluteBoundingBox(),
3160         ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
3161
3162     return nextMatch;
3163 }
3164
3165 RefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
3166 {
3167     if (target.isEmpty())
3168         return nullptr;
3169
3170     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
3171     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
3172     RefPtr<Range> searchRange(rangeOfContents(document()));
3173
3174     bool forward = !(options & Backwards);
3175     bool startInReferenceRange = referenceRange && (options & StartInSelection);
3176     if (referenceRange) {
3177         if (forward)
3178             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
3179         else
3180             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
3181     }
3182
3183     RefPtr<Node> shadowTreeRoot = referenceRange ? referenceRange->startContainer().nonBoundaryShadowTreeRootNode() : nullptr;
3184     if (shadowTreeRoot) {
3185         if (forward)
3186             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3187         else
3188             searchRange->setStart(*shadowTreeRoot, 0);
3189     }
3190
3191     RefPtr<Range> resultRange = findPlainText(*searchRange, target, options);
3192     // If we started in the reference range and the found range exactly matches the reference range, find again.
3193     // Build a selection with the found range to remove collapsed whitespace.
3194     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3195     if (startInReferenceRange && areRangesEqual(VisibleSelection(*resultRange).toNormalizedRange().get(), referenceRange)) {
3196         searchRange = rangeOfContents(document());
3197         if (forward)
3198             searchRange->setStart(referenceRange->endPosition());
3199         else
3200             searchRange->setEnd(referenceRange->startPosition());
3201
3202         if (shadowTreeRoot) {
3203             if (forward)
3204                 searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3205             else
3206                 searchRange->setStart(*shadowTreeRoot, 0);
3207         }
3208
3209         resultRange = findPlainText(*searchRange, target, options);
3210     }
3211
3212     // If nothing was found in the shadow tree, search in main content following the shadow tree.
3213     if (resultRange->collapsed() && shadowTreeRoot) {
3214         searchRange = rangeOfContents(document());
3215         if (shadowTreeRoot->shadowHost()) {
3216             if (forward)
3217                 searchRange->setStartAfter(*shadowTreeRoot->shadowHost());
3218             else
3219                 searchRange->setEndBefore(*shadowTreeRoot->shadowHost());
3220         }
3221
3222         resultRange = findPlainText(*searchRange, target, options);
3223     }
3224
3225     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3226     // redundantly re-search the area already searched in some cases).
3227     if (resultRange->collapsed() && options & WrapAround) {
3228         searchRange = rangeOfContents(document());
3229         resultRange = findPlainText(*searchRange, target, options);
3230         // We used to return false here if we ended up with the same range that we started with
3231         // (e.g., the reference range was already the only instance of this text). But we decided that
3232         // this should be a success case instead, so we'll just fall through in that case.
3233     }
3234
3235     return resultRange->collapsed() ? nullptr : resultRange;
3236 }
3237
3238 static bool isFrameInRange(Frame* frame, Range* range)
3239 {
3240     bool inRange = false;
3241     for (HTMLFrameOwnerElement* ownerElement = frame->ownerElement(); ownerElement; ownerElement = ownerElement->document().ownerElement()) {
3242         if (&ownerElement->document() == &range->ownerDocument()) {
3243             inRange = range->intersectsNode(*ownerElement, IGNORE_EXCEPTION);
3244             break;
3245         }
3246     }
3247     return inRange;
3248 }
3249
3250 unsigned Editor::countMatchesForText(const String& target, Range* range, FindOptions options, unsigned limit, bool markMatches, Vector<RefPtr<Range>>* matches)
3251 {
3252     if (target.isEmpty())
3253         return 0;
3254
3255     RefPtr<Range> searchRange;
3256     if (range) {
3257         if (&range->ownerDocument() == &document())
3258             searchRange = range;
3259         else if (!isFrameInRange(&m_frame, range))
3260             return 0;
3261     }
3262     if (!searchRange)
3263         searchRange = rangeOfContents(document());
3264
3265     Node& originalEndContainer = searchRange->endContainer();
3266     int originalEndOffset = searchRange->endOffset();
3267
3268     unsigned matchCount = 0;
3269     do {
3270         RefPtr<Range> resultRange(findPlainText(*searchRange, target, options & ~Backwards));
3271         if (resultRange->collapsed()) {
3272             if (!resultRange->startContainer().isInShadowTree())
3273                 break;
3274
3275             searchRange->setStartAfter(*resultRange->startContainer().shadowHost(), IGNORE_EXCEPTION);
3276             searchRange->setEnd(originalEndContainer, originalEndOffset, IGNORE_EXCEPTION);
3277             continue;
3278         }
3279
3280         ++matchCount;
3281         if (matches)
3282             matches->append(resultRange);
3283         
3284         if (markMatches)
3285             document().markers().addMarker(resultRange.get(), DocumentMarker::TextMatch);
3286
3287         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
3288         if (limit > 0 && matchCount >= limit)
3289             break;
3290
3291         // Set the new start for the search range to be the end of the previous
3292         // result range. There is no need to use a VisiblePosition here,
3293         // since findPlainText will use a TextIterator to go over the visible
3294         // text nodes. 
3295         searchRange->setStart(resultRange->endContainer(), resultRange->endOffset(), IGNORE_EXCEPTION);
3296
3297         Node* shadowTreeRoot = searchRange->shadowRoot();
3298         if (searchRange->collapsed() && shadowTreeRoot)
3299             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes(), IGNORE_EXCEPTION);
3300     } while (true);
3301
3302     return matchCount;
3303 }
3304
3305 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
3306 {
3307     if (flag == m_areMarkedTextMatchesHighlighted)
3308         return;
3309
3310     m_areMarkedTextMatchesHighlighted = flag;
3311     document().markers().repaintMarkers(DocumentMarker::TextMatch);
3312 }
3313
3314 void Editor::respondToChangedSelection(const VisibleSelection&, FrameSelection::SetSelectionOptions options)
3315 {
3316 #if PLATFORM(IOS)
3317     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
3318     if (m_ignoreCompositionSelectionChange)
3319         return;
3320 #endif
3321
3322     if (client())
3323         client()->respondToChangedSelection(&m_frame);
3324
3325 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3326     if (shouldDetectTelephoneNumbers())
3327         m_telephoneNumberDetectionUpdateTimer.startOneShot(0);
3328 #endif
3329
3330     setStartNewKillRingSequence(true);
3331
3332     if (m_editorUIUpdateTimer.isActive())
3333         return;
3334
3335     // Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
3336     m_editorUIUpdateTimerShouldCheckSpellingAndGrammar = options & FrameSelection::CloseTyping
3337         && !(options & FrameSelection::SpellCorrectionTriggered);
3338     m_editorUIUpdateTimerWasTriggeredByDictation = options & FrameSelection::DictationTriggered;
3339     m_editorUIUpdateTimer.startOneShot(0);
3340 }
3341
3342 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3343
3344 bool Editor::shouldDetectTelephoneNumbers()
3345 {
3346     if (!m_frame.document())
3347         return false;
3348     return document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
3349 }
3350
3351 void Editor::scanSelectionForTelephoneNumbers()
3352 {
3353     if (!shouldDetectTelephoneNumbers() || !client())
3354         return;
3355
3356     m_detectedTelephoneNumberRanges.clear();
3357
3358     Vector<RefPtr<Range>> markedRanges;
3359
3360     FrameSelection& frameSelection = m_frame.selection();
3361     if (!frameSelection.isRange()) {
3362         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3363         return;
3364     }
3365     RefPtr<Range> selectedRange = frameSelection.toNormalizedRange();
3366
3367     // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
3368     static const int charactersToExtend = 15;
3369     const VisibleSelection& visibleSelection = frameSelection.selection();
3370     Position start = visibleSelection.start();
3371     Position end = visibleSelection.end();
3372     for (int i = 0; i < charactersToExtend; ++i) {
3373         start = start.previous(Character);
3374         end = end.next(Character);
3375     }
3376
3377     FrameSelection extendedSelection;
3378     extendedSelection.setStart(start);
3379     extendedSelection.setEnd(end);
3380     RefPtr<Range> extendedRange = extendedSelection.toNormalizedRange();
3381
3382     if (!extendedRange) {
3383         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3384         return;
3385     }
3386
3387     scanRangeForTelephoneNumbers(*extendedRange, extendedRange->text(), markedRanges);
3388
3389     // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
3390     for (auto& range : markedRanges) {
3391         if (rangesOverlap(range.get(), selectedRange.get()))
3392             m_detectedTelephoneNumberRanges.append(range);
3393     }
3394
3395     m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3396 }
3397
3398 void Editor::scanRangeForTelephoneNumbers(Range& range, const StringView& stringView, Vector<RefPtr<Range>>& markedRanges)
3399 {
3400     // Don't scan for phone numbers inside editable regions.
3401     Node& startNode = range.startContainer();
3402     if (startNode.hasEditableStyle())
3403         return;
3404
3405     // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
3406     // relative to the scannerPosition
3407     unsigned length = stringView.length();
3408     unsigned scannerPosition = 0;
3409     int relativeStartPosition = 0;
3410     int relativeEndPosition = 0;
3411
3412     auto characters = stringView.upconvertedCharacters();
3413
3414     while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
3415         // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
3416         // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So subtract 1 to get the same
3417         // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
3418         // to the old parser).
3419         --relativeEndPosition;
3420
3421         ASSERT(scannerPosition + relativeEndPosition < length);
3422
3423         unsigned subrangeOffset = scannerPosition + relativeStartPosition;
3424         unsigned subrangeLength = relativeEndPosition - relativeStartPosition + 1;
3425
3426         RefPtr<Range> subrange = TextIterator::subrange(&range, subrangeOffset, subrangeLength);
3427
3428         markedRanges.append(subrange);
3429         range.ownerDocument().markers().addMarker(subrange.get(), DocumentMarker::TelephoneNumber);
3430
3431         scannerPosition += relativeEndPosition + 1;
3432     }
3433 }
3434
3435 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3436
3437 void Editor::updateEditorUINowIfScheduled()
3438 {
3439     if (!m_editorUIUpdateTimer.isActive())
3440         return;
3441     m_editorUIUpdateTimer.stop();
3442     editorUIUpdateTimerFired();
3443 }
3444
3445 void Editor::editorUIUpdateTimerFired()
3446 {
3447     VisibleSelection oldSelection = m_oldSelectionForEditorUIUpdate;
3448
3449     m_alternativeTextController->stopPendingCorrection(oldSelection);
3450     
3451     bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabled();
3452     bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && isGrammarCheckingEnabled();
3453     if (isContinuousSpellCheckingEnabled) {
3454         VisibleSelection newAdjacentWords;
3455         VisibleSelection newSelectedSentence;
3456         bool caretBrowsing = m_frame.settings().caretBrowsingEnabled();
3457         if (m_frame.selection().selection().isContentEditable() || caretBrowsing) {
3458             VisiblePosition newStart(m_frame.selection().selection().visibleStart());
3459 #if !PLATFORM(IOS)
3460             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
3461 #else
3462             // If this bug gets fixed, this PLATFORM(IOS) code could be removed:
3463             // <rdar://problem/7259611> Word boundary code on iPhone gives different results than desktop
3464             EWordSide startWordSide = LeftWordIfOnBoundary;
3465             UChar32 c = newStart.characterBefore();
3466             // FIXME: VisiblePosition::characterAfter() and characterBefore() do not emit newlines the same
3467             // way as TextIterator, so we do an isStartOfParagraph check here.
3468             if (isSpaceOrNewline(c) || c == 0xA0 || isStartOfParagraph(newStart)) {
3469                 startWordSide = RightWordIfOnBoundary;
3470             }
3471             newAdjacentWords = VisibleSelection(startOfWord(newStart, startWordSide), endOfWord(newStart, RightWordIfOnBoundary));
3472 #endif // !PLATFORM(IOS)
3473             if (isContinuousGrammarCheckingEnabled)
3474                 newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
3475         }
3476
3477         // When typing we check spelling elsewhere, so don't redo it here.
3478         // If this is a change in selection resulting from a delete operation,
3479         // oldSelection may no longer be in the document.
3480         if (m_editorUIUpdateTimerShouldCheckSpellingAndGrammar && oldSelection.isContentEditable() && oldSelection.start().deprecatedNode() && oldSelection.start().anchorNode()->inDocument()) {
3481             VisiblePosition oldStart(oldSelection.visibleStart());
3482             VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
3483             if (oldAdjacentWords != newAdjacentWords) {
3484                 if (isContinuousGrammarCheckingEnabled) {
3485                     VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
3486                     markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence);
3487                 } else
3488                     markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
3489             }
3490         }
3491
3492         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)) {
3493             if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
3494                 document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling);
3495         }
3496         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeGrammar)) {
3497             if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
3498                 document().markers().removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
3499         }
3500     }
3501
3502     // When continuous spell checking is off, existing markers disappear after the selection changes.
3503     if (!isContinuousSpellCheckingEnabled)
3504         document().markers().removeMarkers(DocumentMarker::Spelling);
3505     if (!isContinuousGrammarCheckingEnabled)
3506         document().markers().removeMarkers(DocumentMarker::Grammar);
3507
3508     if (!m_editorUIUpdateTimerWasTriggeredByDictation)
3509         m_alternativeTextController->respondToChangedSelection(oldSelection);
3510
3511     m_oldSelectionForEditorUIUpdate = m_frame.selection().selection();
3512 }
3513
3514 static Node* findFirstMarkable(Node* node)
3515 {
3516     while (node) {
3517         if (!node->renderer())
3518             return nullptr;
3519         if (node->renderer()->isTextOrLineBreak())
3520             return node;
3521         if (is<HTMLTextFormControlElement>(*node))
3522             node = downcast<HTMLTextFormControlElement>(*node).visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
3523         else if (node->firstChild())
3524             node = node->firstChild();
3525         else
3526             node = node->nextSibling();
3527     }
3528
3529     return nullptr;
3530 }
3531
3532 bool Editor::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerType, int from, int length) const
3533 {
3534     Node* node = findFirstMarkable(m_frame.selection().selection().start().deprecatedNode());
3535     if (!node)
3536         return false;
3537
3538     unsigned int startOffset = static_cast<unsigned int>(from);
3539     unsigned int endOffset = static_cast<unsigned int>(from + length);
3540     Vector<RenderedDocumentMarker*> markers = document().markers().markersFor(node);
3541     for (auto* marker : markers) {
3542         if (marker->startOffset() <= startOffset && endOffset <= marker->endOffset() && marker->type() == markerType)
3543             return true;
3544     }
3545
3546     return false;
3547 }       
3548
3549 TextCheckingTypeMask Editor::resolveTextCheckingTypeMask(TextCheckingTypeMask textCheckingOptions)
3550 {
3551     bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
3552     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
3553 #if !PLATFORM(IOS)
3554     bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
3555     bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
3556 #endif
3557
3558     TextCheckingTypeMask checkingTypes = 0;
3559     if (shouldMarkSpelling)
3560         checkingTypes |= TextCheckingTypeSpelling;
3561     if (shouldMarkGrammar)
3562         checkingTypes |= TextCheckingTypeGrammar;
3563 #if !PLATFORM(IOS)
3564     if (shouldCheckForCorrection)
3565         checkingTypes |= TextCheckingTypeCorrection;
3566     if (shouldShowCorrectionPanel)
3567         checkingTypes |= TextCheckingTypeShowCorrectionPanel;
3568
3569 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
3570     bool shouldPerformReplacement = textCheckingOptions & TextCheckingTypeReplacement;
3571     if (shouldPerformReplacement) {
3572         if (isAutomaticLinkDetectionEnabled())
3573             checkingTypes |= TextCheckingTypeLink;
3574         if (isAutomaticQuoteSubstitutionEnabled())
3575             checkingTypes |= TextCheckingTypeQuote;
3576         if (isAutomaticDashSubstitutionEnabled())
3577             checkingTypes |= TextCheckingTypeDash;
3578         if (isAutomaticTextReplacementEnabled())
3579             checkingTypes |= TextCheckingTypeReplacement;
3580         if (shouldMarkSpelling && isAutomaticSpellingCorrectionEnabled())
3581             checkingTypes |= TextCheckingTypeCorrection;
3582     }
3583 #endif
3584 #endif // !PLATFORM(IOS)
3585
3586     return checkingTypes;
3587 }
3588
3589 static RefPtr<Range> candidateRangeForSelection(Frame& frame)
3590 {
3591     const VisibleSelection& selection = frame.selection().selection();
3592     return selection.isCaret() ? wordRangeFromPosition(selection.start()) : frame.selection().toNormalizedRange();
3593 }
3594
3595 static bool candidateWouldReplaceText(const VisibleSelection& selection)
3596 {
3597     // If the character behind the caret in the current selection is anything but a space or a newline then we should
3598     // replace the whole current word with the candidate.
3599     UChar32 characterAfterSelection, characterBeforeSelection, twoCharacterBeforeSelection = 0;
3600     charactersAroundPosition(selection.visibleStart(), characterAfterSelection, characterBeforeSelection, twoCharacterBeforeSelection);
3601     return !(characterBeforeSelection == '\0' || characterBeforeSelection == '\n' || characterBeforeSelection == ' ');
3602 }
3603
3604 String Editor::stringForCandidateRequest() const
3605 {
3606     const VisibleSelection& selection = m_frame.selection().selection();
3607     RefPtr<Range> rangeForCurrentlyTypedString = candidateRangeForSelection(m_frame);
3608     if (rangeForCurrentlyTypedString && candidateWouldReplaceText(selection))
3609         return plainText(rangeForCurrentlyTypedString.get());
3610
3611     return String();
3612 }
3613     
3614 RefPtr<Range> Editor::contextRangeForCandidateRequest() const
3615 {
3616     const VisibleSelection& selection = m_frame.selection().selection();
3617     return makeRange(startOfParagraph(selection.visibleStart()), endOfParagraph(selection.visibleEnd()));
3618 }
3619     
3620 void Editor::selectTextCheckingResult(const TextCheckingResult& result)
3621 {
3622     if (!result.length)
3623         return;
3624     
3625     RefPtr<Range> contextRange = contextRangeForCandidateRequest();
3626     if (!contextRange)
3627         return;
3628     
3629     RefPtr<Range> replacementRange = TextIterator::subrange(contextRange.get(), result.location, result.length);
3630     if (!replacementRange)
3631         return;
3632     
3633     m_frame.selection().setSelectedRange(replacementRange.get(), UPSTREAM, true);
3634 }
3635
3636 void Editor::handleAcceptedCandidate(TextCheckingResult acceptedCandidate)
3637 {
3638     const VisibleSelection& selection = m_frame.selection().selection();
3639     int candidateLength = acceptedCandidate.length;
3640
3641     m_isHandlingAcceptedCandidate = true;
3642
3643     selectTextCheckingResult(acceptedCandidate);
3644     insertText(acceptedCandidate.replacement, 0);
3645
3646     // Some candidates come with a space built in, and we do not need to add another space in that case.
3647     if (!acceptedCandidate.replacement.endsWith(' ')) {
3648         insertText(ASCIILiteral(" "), 0);
3649         ++candidateLength;
3650     }
3651
3652     RefPtr<Range> insertedCandidateRange = rangeExpandedAroundPositionByCharacters(selection.visibleStart(), candidateLength);
3653     if (insertedCandidateRange)
3654         insertedCandidateRange->startContainer().document().markers().addMarker(insertedCandidateRange.get(), DocumentMarker::AcceptedCandidate, acceptedCandidate.replacement);
3655
3656     m_isHandlingAcceptedCandidate = false;
3657 }
3658
3659 bool Editor::unifiedTextCheckerEnabled() const
3660 {
3661     return WebCore::unifiedTextCheckerEnabled(&m_frame);
3662 }
3663
3664 Vector<String> Editor::dictationAlternativesForMarker(const DocumentMarker* marker)
3665 {
3666     return m_alternativeTextController->dictationAlternativesForMarker(marker);
3667 }
3668
3669 void Editor::applyDictationAlternativelternative(const String& alternativeString)
3670 {
3671     m_alternativeTextController->applyDictationAlternative(alternativeString);
3672 }
3673
3674 void Editor::toggleOverwriteModeEnabled()
3675 {
3676     m_overwriteModeEnabled = !m_overwriteModeEnabled;
3677     m_frame.selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
3678 }
3679
3680 Document& Editor::document() const
3681 {
3682     ASSERT(m_frame.document());
3683     return *m_frame.document();
3684 }
3685
3686 } // namespace WebCore