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