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