Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2011, 2013-2015 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "Editor.h"
29
30 #include "AXObjectCache.h"
31 #include "AlternativeTextController.h"
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSPropertyNames.h"
35 #include "CachedResourceLoader.h"
36 #include "ClipboardEvent.h"
37 #include "CompositionEvent.h"
38 #include "CreateLinkCommand.h"
39 #include "DataTransfer.h"
40 #include "DeleteSelectionCommand.h"
41 #include "DictationAlternative.h"
42 #include "DictationCommand.h"
43 #include "DocumentFragment.h"
44 #include "DocumentMarkerController.h"
45 #include "EditorClient.h"
46 #include "EventHandler.h"
47 #include "EventNames.h"
48 #include "ExceptionCodePlaceholder.h"
49 #include "FocusController.h"
50 #include "Frame.h"
51 #include "FrameTree.h"
52 #include "FrameView.h"
53 #include "GraphicsContext.h"
54 #include "HTMLCollection.h"
55 #include "HTMLFormControlElement.h"
56 #include "HTMLFrameOwnerElement.h"
57 #include "HTMLImageElement.h"
58 #include "HTMLNames.h"
59 #include "HTMLTextAreaElement.h"
60 #include "HitTestResult.h"
61 #include "IndentOutdentCommand.h"
62 #include "InsertListCommand.h"
63 #include "KeyboardEvent.h"
64 #include "KillRing.h"
65 #include "MainFrame.h"
66 #include "ModifySelectionListLevel.h"
67 #include "NodeList.h"
68 #include "NodeTraversal.h"
69 #include "Page.h"
70 #include "Pasteboard.h"
71 #include "Range.h"
72 #include "RemoveFormatCommand.h"
73 #include "RenderBlock.h"
74 #include "RenderTextControl.h"
75 #include "RenderedDocumentMarker.h"
76 #include "RenderedPosition.h"
77 #include "ReplaceSelectionCommand.h"
78 #include "Settings.h"
79 #include "ShadowRoot.h"
80 #include "SimplifyMarkupCommand.h"
81 #include "Sound.h"
82 #include "SpellChecker.h"
83 #include "SpellingCorrectionCommand.h"
84 #include "StyleProperties.h"
85 #include "TelephoneNumberDetector.h"
86 #include "Text.h"
87 #include "TextCheckerClient.h"
88 #include "TextCheckingHelper.h"
89 #include "TextEvent.h"
90 #include "TextIterator.h"
91 #include "TypingCommand.h"
92 #include "UserTypingGestureIndicator.h"
93 #include "VisibleUnits.h"
94 #include "htmlediting.h"
95 #include "markup.h"
96 #include <wtf/unicode/CharacterNames.h>
97
98 #if PLATFORM(IOS)
99 #include "DictationCommandIOS.h"
100 #include <wtf/text/StringBuilder.h>
101 #include <wtf/text/WTFString.h>
102 #endif
103
104 #if PLATFORM(MAC)
105 #include "ServicesOverlayController.h"
106 #endif
107
108 namespace WebCore {
109
110 class ClearTextCommand : public DeleteSelectionCommand {
111 public:
112     ClearTextCommand(Document& document);
113     static void CreateAndApply(const RefPtr<Frame> frame);
114     
115 private:
116     virtual EditAction editingAction() const;
117 };
118
119 ClearTextCommand::ClearTextCommand(Document& document)
120     : DeleteSelectionCommand(document, false, true, false, false, true)
121 {
122 }
123
124 EditAction ClearTextCommand::editingAction() const
125 {
126     return EditActionDelete;
127 }
128
129 void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
130 {
131     if (frame->selection().isNone())
132         return;
133
134     // Don't leave around stale composition state.
135     frame->editor().clear();
136     
137     const VisibleSelection oldSelection = frame->selection().selection();
138     frame->selection().selectAll();
139     RefPtr<ClearTextCommand> clearCommand = adoptRef(new ClearTextCommand(*frame->document()));
140     clearCommand->setStartingSelection(oldSelection);
141     applyCommand(clearCommand.release());
142 }
143
144 using namespace HTMLNames;
145 using namespace WTF;
146 using namespace Unicode;
147
148 // When an event handler has moved the selection outside of a text control
149 // we should use the target control's selection for this editing operation.
150 VisibleSelection Editor::selectionForCommand(Event* event)
151 {
152     VisibleSelection selection = m_frame.selection().selection();
153     if (!event)
154         return selection;
155     // If the target is a text control, and the current selection is outside of its shadow tree,
156     // then use the saved selection for that text control.
157     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
158     HTMLTextFormControlElement* textFromControlOfTarget = is<HTMLTextFormControlElement>(*event->target()->toNode()) ? downcast<HTMLTextFormControlElement>(event->target()->toNode()) : nullptr;
159     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
160         if (RefPtr<Range> range = textFromControlOfTarget->selection())
161             return VisibleSelection(*range, DOWNSTREAM, selection.isDirectional());
162     }
163     return selection;
164 }
165
166 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
167 EditingBehavior Editor::behavior() const
168 {
169     return EditingBehavior(m_frame.settings().editingBehaviorType());
170 }
171
172 EditorClient* Editor::client() const
173 {
174     if (Page* page = m_frame.page())
175         return &page->editorClient();
176     return nullptr;
177 }
178
179 TextCheckerClient* Editor::textChecker() const
180 {
181     if (EditorClient* owner = client())
182         return owner->textChecker();
183     return 0;
184 }
185
186 void Editor::handleKeyboardEvent(KeyboardEvent* event)
187 {
188     if (EditorClient* c = client())
189         c->handleKeyboardEvent(event);
190 }
191
192 void Editor::handleInputMethodKeydown(KeyboardEvent* event)
193 {
194     if (EditorClient* c = client())
195         c->handleInputMethodKeydown(event);
196 }
197
198 bool Editor::handleTextEvent(TextEvent* event)
199 {
200     // Default event handling for Drag and Drop will be handled by DragController
201     // so we leave the event for it.
202     if (event->isDrop())
203         return false;
204
205     if (event->isPaste()) {
206         if (event->pastingFragment())
207 #if PLATFORM(IOS)
208         {
209             if (client()->performsTwoStepPaste(event->pastingFragment()))
210                 return true;
211 #endif
212             replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle(), EditActionPaste, event->mailBlockquoteHandling());
213 #if PLATFORM(IOS)
214         }
215 #endif
216         else 
217             replaceSelectionWithText(event->data(), false, event->shouldSmartReplace(), EditActionPaste);
218         return true;
219     }
220
221     String data = event->data();
222     if (data == "\n") {
223         if (event->isLineBreak())
224             return insertLineBreak();
225         return insertParagraphSeparator();
226     }
227
228     return insertTextWithoutSendingTextEvent(data, false, event);
229 }
230
231 bool Editor::canEdit() const
232 {
233     return m_frame.selection().selection().rootEditableElement();
234 }
235
236 bool Editor::canEditRichly() const
237 {
238     return m_frame.selection().selection().isContentRichlyEditable();
239 }
240
241 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
242 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
243 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
244 // normally selectable to implement copy/paste (like divs, or a document body).
245
246 bool Editor::canDHTMLCut()
247 {
248     return !m_frame.selection().selection().isInPasswordField() && !dispatchCPPEvent(eventNames().beforecutEvent, DataTransferAccessPolicy::Numb);
249 }
250
251 bool Editor::canDHTMLCopy()
252 {
253     return !m_frame.selection().selection().isInPasswordField() && !dispatchCPPEvent(eventNames().beforecopyEvent, DataTransferAccessPolicy::Numb);
254 }
255
256 bool Editor::canDHTMLPaste()
257 {
258     return !dispatchCPPEvent(eventNames().beforepasteEvent, DataTransferAccessPolicy::Numb);
259 }
260
261 bool Editor::canCut() const
262 {
263     return canCopy() && canDelete();
264 }
265
266 static HTMLImageElement* imageElementFromImageDocument(Document& document)
267 {
268     if (!document.isImageDocument())
269         return nullptr;
270     
271     HTMLElement* body = document.bodyOrFrameset();
272     if (!body)
273         return nullptr;
274     
275     Node* node = body->firstChild();
276     if (!is<HTMLImageElement>(node))
277         return nullptr;
278     return downcast<HTMLImageElement>(node);
279 }
280
281 bool Editor::canCopy() const
282 {
283     if (imageElementFromImageDocument(document()))
284         return true;
285     const VisibleSelection& selection = m_frame.selection().selection();
286     return selection.isRange() && !selection.isInPasswordField();
287 }
288
289 bool Editor::canPaste() const
290 {
291     return canEdit();
292 }
293
294 bool Editor::canDelete() const
295 {
296     const VisibleSelection& selection = m_frame.selection().selection();
297     return selection.isRange() && selection.rootEditableElement();
298 }
299
300 bool Editor::canDeleteRange(Range* range) const
301 {
302     Node& startContainer = range->startContainer();
303     Node& endContainer = range->endContainer();
304     
305     if (!startContainer.hasEditableStyle() || !endContainer.hasEditableStyle())
306         return false;
307
308     if (range->collapsed()) {
309         VisiblePosition start(range->startPosition(), DOWNSTREAM);
310         VisiblePosition previous = start.previous();
311         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
312         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer.rootEditableElement())
313             return false;
314     }
315     return true;
316 }
317
318 bool Editor::smartInsertDeleteEnabled()
319 {   
320     return client() && client()->smartInsertDeleteEnabled();
321 }
322     
323 bool Editor::canSmartCopyOrDelete()
324 {
325     return client() && client()->smartInsertDeleteEnabled() && m_frame.selection().granularity() == WordGranularity;
326 }
327
328 bool Editor::isSelectTrailingWhitespaceEnabled()
329 {
330     return client() && client()->isSelectTrailingWhitespaceEnabled();
331 }
332
333 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool shouldAddToKillRing, bool isTypingAction)
334 {
335     if (!canEdit())
336         return false;
337
338     if (m_frame.selection().isRange()) {
339         if (isTypingAction) {
340             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
341             revealSelectionAfterEditingOperation();
342         } else {
343             if (shouldAddToKillRing)
344                 addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
345             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
346             // Implicitly calls revealSelectionAfterEditingOperation().
347         }
348     } else {
349         TypingCommand::Options options = 0;
350         if (canSmartCopyOrDelete())
351             options |= TypingCommand::SmartDelete;
352         if (shouldAddToKillRing)
353             options |= TypingCommand::AddsToKillRing;
354         switch (direction) {
355         case DirectionForward:
356         case DirectionRight:
357             TypingCommand::forwardDeleteKeyPressed(document(), options, granularity);
358             break;
359         case DirectionBackward:
360         case DirectionLeft:
361             TypingCommand::deleteKeyPressed(document(), options, granularity);
362             break;
363         }
364         revealSelectionAfterEditingOperation();
365     }
366
367     // FIXME: We should to move this down into deleteKeyPressed.
368     // clear the "start new kill ring sequence" setting, because it was set to true
369     // when the selection was updated by deleting the range
370     if (shouldAddToKillRing)
371         setStartNewKillRingSequence(false);
372
373     return true;
374 }
375
376 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editingAction)
377 {
378     if (m_frame.selection().isNone())
379         return;
380
381     applyCommand(DeleteSelectionCommand::create(document(), smartDelete, true, false, false, true, editingAction));
382 }
383
384 void Editor::clearText()
385 {
386     ClearTextCommand::CreateAndApply(&m_frame);
387 }
388
389 #if PLATFORM(IOS)
390
391 void Editor::insertDictationPhrases(Vector<Vector<String>>&& dictationPhrases, RetainPtr<id> metadata)
392 {
393     if (m_frame.selection().isNone())
394         return;
395
396     if (dictationPhrases.isEmpty())
397         return;
398
399     applyCommand(DictationCommandIOS::create(document(), WTFMove(dictationPhrases), WTFMove(metadata)));
400 }
401
402 void Editor::setDictationPhrasesAsChildOfElement(const Vector<Vector<String>>& dictationPhrases, RetainPtr<id> metadata, Element& element)
403 {
404     // Clear the composition.
405     clear();
406     
407     // Clear the Undo stack, since the operations that follow are not Undoable, and will corrupt the stack.  Some day
408     // we could make them Undoable, and let callers clear the Undo stack explicitly if they wish.
409     clearUndoRedoOperations();
410     
411     m_frame.selection().clear();
412     
413     element.removeChildren();
414     
415     if (dictationPhrases.isEmpty()) {
416         client()->respondToChangedContents();
417         return;
418     }
419     
420     ExceptionCode ec;    
421     RefPtr<Range> context = document().createRange();
422     context->selectNodeContents(&element, ec);
423
424     StringBuilder dictationPhrasesBuilder;
425     for (auto& interpretations : dictationPhrases)
426         dictationPhrasesBuilder.append(interpretations[0]);
427
428     element.appendChild(createFragmentFromText(*context, dictationPhrasesBuilder.toString()), ec);
429
430     // We need a layout in order to add markers below.
431     document().updateLayout();
432
433     if (!element.firstChild()->isTextNode()) {
434         // Shouldn't happen.
435         ASSERT(element.firstChild()->isTextNode());
436         return;
437     }
438
439     Text& textNode = downcast<Text>(*element.firstChild());
440     int previousDictationPhraseStart = 0;
441     for (auto& interpretations : dictationPhrases) {
442         int dictationPhraseLength = interpretations[0].length();
443         int dictationPhraseEnd = previousDictationPhraseStart + dictationPhraseLength;
444         if (interpretations.size() > 1) {
445             auto dictationPhraseRange = Range::create(document(), &textNode, previousDictationPhraseStart, &textNode, dictationPhraseEnd);
446             document().markers().addDictationPhraseWithAlternativesMarker(dictationPhraseRange.ptr(), interpretations);
447         }
448         previousDictationPhraseStart = dictationPhraseEnd;
449     }
450
451     auto resultRange = Range::create(document(), &textNode, 0, &textNode, textNode.length());
452     document().markers().addDictationResultMarker(resultRange.ptr(), metadata);
453
454     client()->respondToChangedContents();
455 }
456
457 #endif
458
459 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
460 {
461     Node* target = findEventTargetFromSelection();
462     if (!target)
463         return;
464     target->dispatchEvent(TextEvent::createForPlainTextPaste(document().domWindow(), pastingText, smartReplace));
465 }
466
467 void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
468 {
469     Node* target = findEventTargetFromSelection();
470     if (!target)
471         return;
472     target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle, respectsMailBlockquote));
473 }
474
475 void Editor::pasteAsPlainTextBypassingDHTML()
476 {
477     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
478 }
479
480 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard& pasteboard)
481 {
482     String text = readPlainTextFromPasteboard(pasteboard);
483     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertActionPasted))
484         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
485 }
486
487 String Editor::readPlainTextFromPasteboard(Pasteboard& pasteboard)
488 {
489     PasteboardPlainText text;
490     pasteboard.read(text);
491     return plainTextFromPasteboard(text);
492 }
493
494 #if !PLATFORM(MAC)
495
496 String Editor::plainTextFromPasteboard(const PasteboardPlainText& text)
497 {
498     return text.text;
499 }
500
501 #endif
502
503 bool Editor::canSmartReplaceWithPasteboard(Pasteboard& pasteboard)
504 {
505     return client() && client()->smartInsertDeleteEnabled() && pasteboard.canSmartReplace();
506 }
507
508 bool Editor::shouldInsertFragment(PassRefPtr<DocumentFragment> fragment, PassRefPtr<Range> replacingDOMRange, EditorInsertAction givenAction)
509 {
510     if (!client())
511         return false;
512     
513     if (fragment) {
514         Node* child = fragment->firstChild();
515         if (is<CharacterData>(child) && fragment->lastChild() == child)
516             return client()->shouldInsertText(downcast<CharacterData>(*child).data(), replacingDOMRange.get(), givenAction);
517     }
518
519     return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
520 }
521
522 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
523 {
524     VisibleSelection selection = m_frame.selection().selection();
525     if (selection.isNone() || !selection.isContentEditable() || !fragment)
526         return;
527
528     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
529     if (selectReplacement)
530         options |= ReplaceSelectionCommand::SelectReplacement;
531     if (smartReplace)
532         options |= ReplaceSelectionCommand::SmartReplace;
533     if (matchStyle)
534         options |= ReplaceSelectionCommand::MatchStyle;
535     if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
536         options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
537
538     applyCommand(ReplaceSelectionCommand::create(document(), fragment, options, editingAction));
539     revealSelectionAfterEditingOperation();
540
541     selection = m_frame.selection().selection();
542     if (selection.isInPasswordField() || !isContinuousSpellCheckingEnabled())
543         return;
544     Node* nodeToCheck = selection.rootEditableElement();
545     if (!nodeToCheck)
546         return;
547
548     RefPtr<Range> rangeToCheck = Range::create(document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
549     m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck, rangeToCheck));
550 }
551
552 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace, EditAction editingAction)
553 {
554     RefPtr<Range> range = selectedRange();
555     if (!range)
556         return;
557
558     replaceSelectionWithFragment(createFragmentFromText(*range, text), selectReplacement, smartReplace, true, editingAction);
559 }
560
561 PassRefPtr<Range> Editor::selectedRange()
562 {
563     return m_frame.selection().toNormalizedRange();
564 }
565
566 #if PLATFORM(IOS)
567 void Editor::confirmMarkedText()
568 {
569     // FIXME: This is a hacky workaround for the keyboard calling this method too late -
570     // after the selection and focus have already changed.  See <rdar://problem/5975559>
571     Element* focused = document().focusedElement();
572     Node* composition = compositionNode();
573     
574     if (composition && focused && focused != composition && !composition->isDescendantOrShadowDescendantOf(focused)) {
575         cancelComposition();
576         document().setFocusedElement(focused);
577     } else
578         confirmComposition();
579 }
580
581 void Editor::setTextAsChildOfElement(const String& text, Element* elem)
582 {
583     // Clear the composition
584     clear();
585     
586     // Clear the Undo stack, since the operations that follow are not Undoable, and will corrupt the stack.  Some day
587     // we could make them Undoable, and let callers clear the Undo stack explicitly if they wish.
588     clearUndoRedoOperations();
589     
590     // If the element is empty already and we're not adding text, we can early return and avoid clearing/setting
591     // a selection at [0, 0] and the expense involved in creation VisiblePositions.
592     if (!elem->firstChild() && text.isEmpty())
593         return;
594     
595     // As a side effect this function sets a caret selection after the inserted content.  Much of what 
596     // follows is more expensive if there is a selection, so clear it since it's going to change anyway.
597     m_frame.selection().clear();
598     
599     // clear out all current children of element
600     elem->removeChildren();
601
602     if (text.length()) {
603         // insert new text
604         // remove element from tree while doing it
605         // FIXME: The element we're inserting into is often the body element.  It seems strange to be removing it
606         // (even if it is only temporary).  ReplaceSelectionCommand doesn't bother doing this when it inserts
607         // content, why should we here?
608         ExceptionCode ec;
609         RefPtr<Node> parent = elem->parentNode();
610         RefPtr<Node> siblingAfter = elem->nextSibling();
611         if (parent)
612             elem->remove(ec);    
613             
614         RefPtr<Range> context = document().createRange();
615         context->selectNodeContents(elem, ec);
616         Ref<DocumentFragment> fragment = createFragmentFromText(*context.get(), text);
617         elem->appendChild(WTFMove(fragment), ec);
618     
619         // restore element to document
620         if (parent) {
621             if (siblingAfter)
622                 parent->insertBefore(elem, siblingAfter.get(), ec);
623             else
624                 parent->appendChild(elem, ec);
625         }
626     }
627
628     // set the selection to the end
629     VisibleSelection selection;
630
631     Position pos = createLegacyEditingPosition(elem, elem->countChildNodes());
632
633     VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
634     if (visiblePos.isNull())
635         return;
636
637     selection.setBase(visiblePos);
638     selection.setExtent(visiblePos);
639      
640     m_frame.selection().setSelection(selection);
641     
642     client()->respondToChangedContents();
643 }
644 #endif
645
646 bool Editor::shouldDeleteRange(Range* range) const
647 {
648     if (!range || range->collapsed())
649         return false;
650     
651     if (!canDeleteRange(range))
652         return false;
653
654     return client() && client()->shouldDeleteRange(range);
655 }
656
657 bool Editor::tryDHTMLCopy()
658 {   
659     if (m_frame.selection().selection().isInPasswordField())
660         return false;
661
662     return !dispatchCPPEvent(eventNames().copyEvent, DataTransferAccessPolicy::Writable);
663 }
664
665 bool Editor::tryDHTMLCut()
666 {
667     if (m_frame.selection().selection().isInPasswordField())
668         return false;
669     
670     return !dispatchCPPEvent(eventNames().cutEvent, DataTransferAccessPolicy::Writable);
671 }
672
673 bool Editor::tryDHTMLPaste()
674 {
675     return !dispatchCPPEvent(eventNames().pasteEvent, DataTransferAccessPolicy::Readable);
676 }
677
678 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
679 {
680     return client() && client()->shouldInsertText(text, range, action);
681 }
682
683 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
684 {
685     if (AXObjectCache::accessibilityEnabled()) {
686         Node* node = endingSelection.start().deprecatedNode();
687         if (AXObjectCache* cache = document().existingAXObjectCache())
688             cache->postNotification(node, AXObjectCache::AXValueChanged, TargetObservableParent);
689     }
690
691     updateMarkersForWordsAffectedByEditing(true);
692
693     if (client())
694         client()->respondToChangedContents();
695 }
696
697 bool Editor::hasBidiSelection() const
698 {
699     if (m_frame.selection().isNone())
700         return false;
701
702     Node* startNode;
703     if (m_frame.selection().isRange()) {
704         startNode = m_frame.selection().selection().start().downstream().deprecatedNode();
705         Node* endNode = m_frame.selection().selection().end().upstream().deprecatedNode();
706         if (enclosingBlock(startNode) != enclosingBlock(endNode))
707             return false;
708     } else
709         startNode = m_frame.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
710
711     if (!startNode)
712         return false;
713
714     auto renderer = startNode->renderer();
715     while (renderer && !is<RenderBlockFlow>(*renderer))
716         renderer = renderer->parent();
717
718     if (!renderer)
719         return false;
720
721     if (!renderer->style().isLeftToRightDirection())
722         return true;
723
724     return downcast<RenderBlockFlow>(*renderer).containsNonZeroBidiLevel();
725 }
726
727 TriState Editor::selectionUnorderedListState() const
728 {
729     if (m_frame.selection().isCaret()) {
730         if (enclosingElementWithTag(m_frame.selection().selection().start(), ulTag))
731             return TrueTriState;
732     } else if (m_frame.selection().isRange()) {
733         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), ulTag);
734         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), ulTag);
735         if (startNode && endNode && startNode == endNode)
736             return TrueTriState;
737     }
738
739     return FalseTriState;
740 }
741
742 TriState Editor::selectionOrderedListState() const
743 {
744     if (m_frame.selection().isCaret()) {
745         if (enclosingElementWithTag(m_frame.selection().selection().start(), olTag))
746             return TrueTriState;
747     } else if (m_frame.selection().isRange()) {
748         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), olTag);
749         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), olTag);
750         if (startNode && endNode && startNode == endNode)
751             return TrueTriState;
752     }
753
754     return FalseTriState;
755 }
756
757 PassRefPtr<Node> Editor::insertOrderedList()
758 {
759     if (!canEditRichly())
760         return 0;
761         
762     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::OrderedList);
763     revealSelectionAfterEditingOperation();
764     return newList;
765 }
766
767 PassRefPtr<Node> Editor::insertUnorderedList()
768 {
769     if (!canEditRichly())
770         return 0;
771         
772     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::UnorderedList);
773     revealSelectionAfterEditingOperation();
774     return newList;
775 }
776
777 bool Editor::canIncreaseSelectionListLevel()
778 {
779     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(&document());
780 }
781
782 bool Editor::canDecreaseSelectionListLevel()
783 {
784     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(&document());
785 }
786
787 PassRefPtr<Node> Editor::increaseSelectionListLevel()
788 {
789     if (!canEditRichly() || m_frame.selection().isNone())
790         return 0;
791     
792     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(&document());
793     revealSelectionAfterEditingOperation();
794     return newList;
795 }
796
797 PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered()
798 {
799     if (!canEditRichly() || m_frame.selection().isNone())
800         return 0;
801     
802     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(&document());
803     revealSelectionAfterEditingOperation();
804     return newList.release();
805 }
806
807 PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
808 {
809     if (!canEditRichly() || m_frame.selection().isNone())
810         return 0;
811     
812     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(&document());
813     revealSelectionAfterEditingOperation();
814     return newList.release();
815 }
816
817 void Editor::decreaseSelectionListLevel()
818 {
819     if (!canEditRichly() || m_frame.selection().isNone())
820         return;
821     
822     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(&document());
823     revealSelectionAfterEditingOperation();
824 }
825
826 void Editor::removeFormattingAndStyle()
827 {
828     applyCommand(RemoveFormatCommand::create(document()));
829 }
830
831 void Editor::clearLastEditCommand() 
832 {
833     m_lastEditCommand = nullptr;
834 }
835 #if PLATFORM(IOS)
836 // If the selection is adjusted from UIKit without closing the typing, the typing command may
837 // have a stale selection.
838 void Editor::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping()
839 {
840     TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(&m_frame, m_frame.selection().selection());
841 }
842 #endif
843
844 // Returns whether caller should continue with "the default processing", which is the same as 
845 // the event handler NOT setting the return value to false
846 bool Editor::dispatchCPPEvent(const AtomicString& eventType, DataTransferAccessPolicy policy)
847 {
848     Node* target = findEventTargetFromSelection();
849     if (!target)
850         return true;
851
852     RefPtr<DataTransfer> dataTransfer = DataTransfer::createForCopyAndPaste(policy);
853
854     Ref<Event> event = ClipboardEvent::create(eventType, true, true, dataTransfer.get());
855     target->dispatchEvent(event);
856     bool noDefaultProcessing = event->defaultPrevented();
857     if (noDefaultProcessing && policy == DataTransferAccessPolicy::Writable) {
858         auto pasteboard = Pasteboard::createForCopyAndPaste();
859         pasteboard->clear();
860         pasteboard->writePasteboard(dataTransfer->pasteboard());
861     }
862
863     // invalidate dataTransfer here for security
864     dataTransfer->setAccessPolicy(DataTransferAccessPolicy::Numb);
865     
866     return !noDefaultProcessing;
867 }
868
869 Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const
870 {
871     Node* target = selection.start().element();
872     if (!target)
873         target = document().bodyOrFrameset();
874     if (!target)
875         return nullptr;
876
877     return target;
878 }
879
880 Node* Editor::findEventTargetFromSelection() const
881 {
882     return findEventTargetFrom(m_frame.selection().selection());
883 }
884
885 void Editor::applyStyle(StyleProperties* style, EditAction editingAction)
886 {
887     switch (m_frame.selection().selection().selectionType()) {
888     case VisibleSelection::NoSelection:
889         return;
890     case VisibleSelection::CaretSelection:
891         computeAndSetTypingStyle(EditingStyle::create(style), editingAction);
892         break;
893     case VisibleSelection::RangeSelection:
894         if (style)
895             applyCommand(ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction));
896         break;
897     }
898     client()->didApplyStyle();
899 }
900
901 void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction)
902 {
903     switch (m_frame.selection().selection().selectionType()) {
904     case VisibleSelection::NoSelection:
905         return;
906     case VisibleSelection::CaretSelection:
907         computeAndSetTypingStyle(*style, editingAction);
908         break;
909     case VisibleSelection::RangeSelection:
910         if (style)
911             applyCommand(ApplyStyleCommand::create(document(), style.get(), editingAction));
912         break;
913     }
914     client()->didApplyStyle();
915 }
916     
917 bool Editor::shouldApplyStyle(StyleProperties* style, Range* range)
918 {   
919     return client()->shouldApplyStyle(style, range);
920 }
921     
922 void Editor::applyParagraphStyle(StyleProperties* style, EditAction editingAction)
923 {
924     switch (m_frame.selection().selection().selectionType()) {
925     case VisibleSelection::NoSelection:
926         return;
927     case VisibleSelection::CaretSelection:
928     case VisibleSelection::RangeSelection:
929         if (style)
930             applyCommand(ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction, ApplyStyleCommand::ForceBlockProperties));
931         break;
932     }
933     client()->didApplyStyle();
934 }
935
936 void Editor::applyStyleToSelection(StyleProperties* style, EditAction editingAction)
937 {
938     if (!style || style->isEmpty() || !canEditRichly())
939         return;
940
941     if (!client() || !client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
942         return;
943     applyStyle(style, editingAction);
944 }
945
946 void Editor::applyStyleToSelection(Ref<EditingStyle>&& style, EditAction editingAction)
947 {
948     if (style->isEmpty() || !canEditRichly())
949         return;
950
951     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
952     if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), m_frame.selection().toNormalizedRange().get()))
953         return;
954
955     applyStyle(WTFMove(style), editingAction);
956 }
957
958 void Editor::applyParagraphStyleToSelection(StyleProperties* style, EditAction editingAction)
959 {
960     if (!style || style->isEmpty() || !canEditRichly())
961         return;
962     
963     if (client() && client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
964         applyParagraphStyle(style, editingAction);
965 }
966
967 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
968 {
969     return EditingStyle::create(propertyID, value)->triStateOfStyle(
970         EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor).get());
971 }
972
973 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
974 {
975     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
976 }
977
978 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
979 {
980     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
981         propertyID == CSSPropertyBackgroundColor);
982     if (!selectionStyle || !selectionStyle->style())
983         return String();
984
985     if (propertyID == CSSPropertyFontSize)
986         return String::number(selectionStyle->legacyFontSize(&document()));
987     return selectionStyle->style()->getPropertyValue(propertyID);
988 }
989
990 void Editor::indent()
991 {
992     applyCommand(IndentOutdentCommand::create(document(), IndentOutdentCommand::Indent));
993 }
994
995 void Editor::outdent()
996 {
997     applyCommand(IndentOutdentCommand::create(document(), IndentOutdentCommand::Outdent));
998 }
999
1000 static void notifyTextFromControls(Element* startRoot, Element* endRoot)
1001 {
1002     HTMLTextFormControlElement* startingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(startRoot));
1003     HTMLTextFormControlElement* endingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(endRoot));
1004     if (startingTextControl)
1005         startingTextControl->didEditInnerTextValue();
1006     if (endingTextControl && startingTextControl != endingTextControl)
1007         endingTextControl->didEditInnerTextValue();
1008 }
1009
1010 static void dispatchEditableContentChangedEvents(PassRefPtr<Element> prpStartRoot, PassRefPtr<Element> prpEndRoot)
1011 {
1012     RefPtr<Element> startRoot = prpStartRoot;
1013     RefPtr<Element> endRoot = prpEndRoot;
1014     if (startRoot)
1015         startRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false));
1016     if (endRoot && endRoot != startRoot)
1017         endRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false));
1018 }
1019
1020 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
1021 {
1022     document().updateLayout();
1023
1024     EditCommandComposition* composition = cmd->composition();
1025     ASSERT(composition);
1026     VisibleSelection newSelection(cmd->endingSelection());
1027
1028     notifyTextFromControls(composition->startingRootEditableElement(), composition->endingRootEditableElement());
1029
1030     // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
1031     FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
1032     
1033     changeSelectionAfterCommand(newSelection, options, cmd->applyEditType());
1034     dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement());
1035
1036     updateEditorUINowIfScheduled();
1037     
1038     m_alternativeTextController->respondToAppliedEditing(cmd.get());
1039
1040     if (!cmd->preservesTypingStyle())
1041         m_frame.selection().clearTypingStyle();
1042
1043     // Command will be equal to last edit command only in the case of typing
1044     if (m_lastEditCommand.get() == cmd)
1045         ASSERT(cmd->isTypingCommand());
1046     else {
1047         // Only register a new undo command if the command passed in is
1048         // different from the last command
1049         m_lastEditCommand = cmd;
1050         if (client())
1051             client()->registerUndoStep(m_lastEditCommand->ensureComposition());
1052     }
1053
1054     respondToChangedContents(newSelection);
1055 }
1056
1057 void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd)
1058 {
1059     document().updateLayout();
1060
1061     notifyTextFromControls(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1062
1063     VisibleSelection newSelection(cmd->startingSelection());
1064     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions(), cmd->unapplyEditType());
1065     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1066
1067     updateEditorUINowIfScheduled();
1068
1069     m_alternativeTextController->respondToUnappliedEditing(cmd.get());
1070
1071     m_lastEditCommand = nullptr;
1072     if (client())
1073         client()->registerRedoStep(cmd);
1074     respondToChangedContents(newSelection);
1075 }
1076
1077 void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd)
1078 {
1079     document().updateLayout();
1080
1081     notifyTextFromControls(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1082
1083     VisibleSelection newSelection(cmd->endingSelection());
1084     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1085     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
1086     
1087     updateEditorUINowIfScheduled();
1088
1089     m_lastEditCommand = nullptr;
1090     if (client())
1091         client()->registerUndoStep(cmd);
1092     respondToChangedContents(newSelection);
1093 }
1094
1095 Editor::Editor(Frame& frame)
1096     : m_frame(frame)
1097     , m_ignoreCompositionSelectionChange(false)
1098     // This is off by default, since most editors want this behavior (this matches IE but not FF).
1099     , m_shouldStyleWithCSS(false)
1100     , m_killRing(std::make_unique<KillRing>())
1101     , m_spellChecker(std::make_unique<SpellChecker>(frame))
1102     , m_alternativeTextController(std::make_unique<AlternativeTextController>(frame))
1103     , m_areMarkedTextMatchesHighlighted(false)
1104     , m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv)
1105     , m_overwriteModeEnabled(false)
1106     , m_editorUIUpdateTimer(*this, &Editor::editorUIUpdateTimerFired)
1107     , m_editorUIUpdateTimerShouldCheckSpellingAndGrammar(false)
1108     , m_editorUIUpdateTimerWasTriggeredByDictation(false)
1109 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
1110     , m_telephoneNumberDetectionUpdateTimer(*this, &Editor::scanSelectionForTelephoneNumbers)
1111 #endif
1112 {
1113 }
1114
1115 Editor::~Editor()
1116 {
1117 }
1118
1119 void Editor::clear()
1120 {
1121     if (m_compositionNode) {
1122         m_compositionNode = nullptr;
1123         if (EditorClient* client = this->client())
1124             client->discardedComposition(&m_frame);
1125     }
1126     m_customCompositionUnderlines.clear();
1127     m_shouldStyleWithCSS = false;
1128     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
1129 }
1130
1131 bool Editor::insertText(const String& text, Event* triggeringEvent)
1132 {
1133     return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent);
1134 }
1135
1136 bool Editor::insertTextForConfirmedComposition(const String& text)
1137 {
1138     return m_frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
1139 }
1140
1141 bool Editor::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent)
1142 {
1143     return m_alternativeTextController->insertDictatedText(text, dictationAlternatives, triggeringEvent);
1144 }
1145
1146 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
1147 {
1148     if (text.isEmpty())
1149         return false;
1150
1151     VisibleSelection selection = selectionForCommand(triggeringEvent);
1152     if (!selection.isContentEditable())
1153         return false;
1154     RefPtr<Range> range = selection.toNormalizedRange();
1155
1156     if (!shouldInsertText(text, range.get(), EditorInsertActionTyped))
1157         return true;
1158
1159     updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
1160
1161     bool shouldConsiderApplyingAutocorrection = false;
1162     if (text == " " || text == "\t")
1163         shouldConsiderApplyingAutocorrection = true;
1164
1165     if (text.length() == 1 && u_ispunct(text[0]) && !isAmbiguousBoundaryCharacter(text[0]))
1166         shouldConsiderApplyingAutocorrection = true;
1167
1168     bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1169
1170     // Get the selection to use for the event that triggered this insertText.
1171     // If the event handler changed the selection, we may want to use a different selection
1172     // that is contained in the event target.
1173     selection = selectionForCommand(triggeringEvent);
1174     if (selection.isContentEditable()) {
1175         if (Node* selectionStart = selection.start().deprecatedNode()) {
1176             Ref<Document> document(selectionStart->document());
1177
1178             // Insert the text
1179             if (triggeringEvent && triggeringEvent->isDictation())
1180                 DictationCommand::insertText(document, text, triggeringEvent->dictationAlternatives(), selection);
1181             else {
1182                 TypingCommand::Options options = 0;
1183                 if (selectInsertedText)
1184                     options |= TypingCommand::SelectInsertedText;
1185                 if (autocorrectionWasApplied)
1186                     options |= TypingCommand::RetainAutocorrectionIndicator;
1187                 TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
1188             }
1189
1190             // Reveal the current selection
1191             if (Frame* editedFrame = document->frame())
1192                 if (Page* page = editedFrame->page())
1193                     page->focusController().focusedOrMainFrame().selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
1194         }
1195     }
1196
1197     return true;
1198 }
1199
1200 bool Editor::insertLineBreak()
1201 {
1202     if (!canEdit())
1203         return false;
1204
1205     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertActionTyped))
1206         return true;
1207
1208     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1209     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1210     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1211     TypingCommand::insertLineBreak(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1212     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1213
1214     return true;
1215 }
1216
1217 bool Editor::insertParagraphSeparator()
1218 {
1219     if (!canEdit())
1220         return false;
1221
1222     if (!canEditRichly())
1223         return insertLineBreak();
1224
1225     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertActionTyped))
1226         return true;
1227
1228     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1229     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1230     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1231     TypingCommand::insertParagraphSeparator(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1232     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1233
1234     return true;
1235 }
1236
1237 void Editor::cut()
1238 {
1239     if (tryDHTMLCut())
1240         return; // DHTML did the whole operation
1241     if (!canCut()) {
1242         systemBeep();
1243         return;
1244     }
1245
1246     performCutOrCopy(CutAction);
1247 }
1248
1249 void Editor::copy()
1250 {
1251     if (tryDHTMLCopy())
1252         return; // DHTML did the whole operation
1253     if (!canCopy()) {
1254         systemBeep();
1255         return;
1256     }
1257
1258     performCutOrCopy(CopyAction);
1259 }
1260
1261 void Editor::performCutOrCopy(EditorActionSpecifier action)
1262 {
1263     RefPtr<Range> selection = selectedRange();
1264     willWriteSelectionToPasteboard(selection);
1265     if (action == CutAction) {
1266         if (!shouldDeleteRange(selection.get()))
1267             return;
1268
1269         updateMarkersForWordsAffectedByEditing(true);
1270     }
1271
1272     if (enclosingTextFormControl(m_frame.selection().selection().start()))
1273         Pasteboard::createForCopyAndPaste()->writePlainText(selectedTextForDataTransfer(), canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
1274     else {
1275         HTMLImageElement* imageElement = nullptr;
1276         if (action == CopyAction)
1277             imageElement = imageElementFromImageDocument(document());
1278
1279         if (imageElement) {
1280 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1281             writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *imageElement, document().url(), document().title());
1282 #else
1283             Pasteboard::createForCopyAndPaste()->writeImage(*imageElement, document().url(), document().title());
1284 #endif
1285         } else {
1286 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1287             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
1288 #else
1289             // FIXME: Convert all other platforms to match Mac and delete this.
1290             Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForDataTransfer);
1291 #endif
1292         }
1293     }
1294
1295     didWriteSelectionToPasteboard();
1296     if (action == CutAction)
1297         deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), EditActionCut);
1298 }
1299
1300 void Editor::paste()
1301 {
1302     paste(*Pasteboard::createForCopyAndPaste());
1303 }
1304
1305 void Editor::paste(Pasteboard& pasteboard)
1306 {
1307     if (tryDHTMLPaste())
1308         return; // DHTML did the whole operation
1309     if (!canPaste())
1310         return;
1311     updateMarkersForWordsAffectedByEditing(false);
1312     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
1313     if (m_frame.selection().selection().isContentRichlyEditable())
1314         pasteWithPasteboard(&pasteboard, true);
1315     else
1316         pasteAsPlainTextWithPasteboard(pasteboard);
1317 }
1318
1319 void Editor::pasteAsPlainText()
1320 {
1321     if (tryDHTMLPaste())
1322         return;
1323     if (!canPaste())
1324         return;
1325     updateMarkersForWordsAffectedByEditing(false);
1326     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
1327 }
1328
1329 void Editor::performDelete()
1330 {
1331     if (!canDelete()) {
1332         systemBeep();
1333         return;
1334     }
1335
1336     addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
1337     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
1338
1339     // clear the "start new kill ring sequence" setting, because it was set to true
1340     // when the selection was updated by deleting the range
1341     setStartNewKillRingSequence(false);
1342 }
1343
1344 void Editor::simplifyMarkup(Node* startNode, Node* endNode)
1345 {
1346     if (!startNode)
1347         return;
1348     if (endNode) {
1349         if (&startNode->document() != &endNode->document())
1350             return;
1351         // check if start node is before endNode
1352         Node* node = startNode;
1353         while (node && node != endNode)
1354             node = NodeTraversal::next(*node);
1355         if (!node)
1356             return;
1357     }
1358     
1359     applyCommand(SimplifyMarkupCommand::create(document(), startNode, endNode ? NodeTraversal::next(*endNode) : nullptr));
1360 }
1361
1362 void Editor::copyURL(const URL& url, const String& title)
1363 {
1364     copyURL(url, title, *Pasteboard::createForCopyAndPaste());
1365 }
1366
1367 void Editor::copyURL(const URL& url, const String& title, Pasteboard& pasteboard)
1368 {
1369     PasteboardURL pasteboardURL;
1370     pasteboardURL.url = url;
1371     pasteboardURL.title = title;
1372
1373 #if PLATFORM(MAC)
1374     fillInUserVisibleForm(pasteboardURL);
1375 #endif
1376
1377     pasteboard.write(pasteboardURL);
1378 }
1379
1380 #if !PLATFORM(IOS)
1381 void Editor::copyImage(const HitTestResult& result)
1382 {
1383     Element* element = result.innerNonSharedElement();
1384     if (!element)
1385         return;
1386
1387     URL url = result.absoluteLinkURL();
1388     if (url.isEmpty())
1389         url = result.absoluteImageURL();
1390
1391 #if PLATFORM(COCOA) || PLATFORM(EFL) || PLATFORM(GTK)
1392     writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *element, url, result.altDisplayString());
1393 #else
1394     Pasteboard::createForCopyAndPaste()->writeImage(*element, url, result.altDisplayString());
1395 #endif
1396 }
1397 #endif
1398
1399 bool Editor::isContinuousSpellCheckingEnabled() const
1400 {
1401     return client() && client()->isContinuousSpellCheckingEnabled();
1402 }
1403
1404 void Editor::toggleContinuousSpellChecking()
1405 {
1406     if (client())
1407         client()->toggleContinuousSpellChecking();
1408 }
1409
1410 bool Editor::isGrammarCheckingEnabled()
1411 {
1412     return client() && client()->isGrammarCheckingEnabled();
1413 }
1414
1415 void Editor::toggleGrammarChecking()
1416 {
1417     if (client())
1418         client()->toggleGrammarChecking();
1419 }
1420
1421 int Editor::spellCheckerDocumentTag()
1422 {
1423     return client() ? client()->spellCheckerDocumentTag() : 0;
1424 }
1425
1426 #if USE(APPKIT)
1427
1428 void Editor::uppercaseWord()
1429 {
1430     if (client())
1431         client()->uppercaseWord();
1432 }
1433
1434 void Editor::lowercaseWord()
1435 {
1436     if (client())
1437         client()->lowercaseWord();
1438 }
1439
1440 void Editor::capitalizeWord()
1441 {
1442     if (client())
1443         client()->capitalizeWord();
1444 }
1445     
1446 #endif
1447
1448 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1449
1450 void Editor::showSubstitutionsPanel()
1451 {
1452     if (!client()) {
1453         LOG_ERROR("No NSSpellChecker");
1454         return;
1455     }
1456
1457     if (client()->substitutionsPanelIsShowing()) {
1458         client()->showSubstitutionsPanel(false);
1459         return;
1460     }
1461     client()->showSubstitutionsPanel(true);
1462 }
1463
1464 bool Editor::substitutionsPanelIsShowing()
1465 {
1466     if (!client())
1467         return false;
1468     return client()->substitutionsPanelIsShowing();
1469 }
1470
1471 void Editor::toggleSmartInsertDelete()
1472 {
1473     if (client())
1474         client()->toggleSmartInsertDelete();
1475 }
1476
1477 bool Editor::isAutomaticQuoteSubstitutionEnabled()
1478 {
1479     return client() && client()->isAutomaticQuoteSubstitutionEnabled();
1480 }
1481
1482 void Editor::toggleAutomaticQuoteSubstitution()
1483 {
1484     if (client())
1485         client()->toggleAutomaticQuoteSubstitution();
1486 }
1487
1488 bool Editor::isAutomaticLinkDetectionEnabled()
1489 {
1490     return client() && client()->isAutomaticLinkDetectionEnabled();
1491 }
1492
1493 void Editor::toggleAutomaticLinkDetection()
1494 {
1495     if (client())
1496         client()->toggleAutomaticLinkDetection();
1497 }
1498
1499 bool Editor::isAutomaticDashSubstitutionEnabled()
1500 {
1501     return client() && client()->isAutomaticDashSubstitutionEnabled();
1502 }
1503
1504 void Editor::toggleAutomaticDashSubstitution()
1505 {
1506     if (client())
1507         client()->toggleAutomaticDashSubstitution();
1508 }
1509
1510 bool Editor::isAutomaticTextReplacementEnabled()
1511 {
1512     return client() && client()->isAutomaticTextReplacementEnabled();
1513 }
1514
1515 void Editor::toggleAutomaticTextReplacement()
1516 {
1517     if (client())
1518         client()->toggleAutomaticTextReplacement();
1519 }
1520
1521 bool Editor::isAutomaticSpellingCorrectionEnabled()
1522 {
1523     return m_alternativeTextController->isAutomaticSpellingCorrectionEnabled();
1524 }
1525
1526 void Editor::toggleAutomaticSpellingCorrection()
1527 {
1528     if (client())
1529         client()->toggleAutomaticSpellingCorrection();
1530 }
1531
1532 #endif
1533
1534 bool Editor::shouldEndEditing(Range* range)
1535 {
1536     return client() && client()->shouldEndEditing(range);
1537 }
1538
1539 bool Editor::shouldBeginEditing(Range* range)
1540 {
1541     return client() && client()->shouldBeginEditing(range);
1542 }
1543
1544 void Editor::clearUndoRedoOperations()
1545 {
1546     if (client())
1547         client()->clearUndoRedoOperations();
1548 }
1549
1550 bool Editor::canUndo()
1551 {
1552     return client() && client()->canUndo();
1553 }
1554
1555 void Editor::undo()
1556 {
1557     if (client())
1558         client()->undo();
1559 }
1560
1561 bool Editor::canRedo()
1562 {
1563     return client() && client()->canRedo();
1564 }
1565
1566 void Editor::redo()
1567 {
1568     if (client())
1569         client()->redo();
1570 }
1571
1572 void Editor::didBeginEditing()
1573 {
1574     if (client())
1575         client()->didBeginEditing();
1576 }
1577
1578 void Editor::didEndEditing()
1579 {
1580     if (client())
1581         client()->didEndEditing();
1582 }
1583
1584 void Editor::willWriteSelectionToPasteboard(PassRefPtr<Range> range)
1585 {
1586     if (client())
1587         client()->willWriteSelectionToPasteboard(range.get());
1588 }
1589
1590 void Editor::didWriteSelectionToPasteboard()
1591 {
1592     if (client())
1593         client()->didWriteSelectionToPasteboard();
1594 }
1595
1596 void Editor::toggleBold()
1597 {
1598     command("ToggleBold").execute();
1599 }
1600
1601 void Editor::toggleUnderline()
1602 {
1603     command("ToggleUnderline").execute();
1604 }
1605
1606 void Editor::setBaseWritingDirection(WritingDirection direction)
1607 {
1608 #if PLATFORM(IOS)
1609     if (inSameParagraph(m_frame.selection().selection().visibleStart(), m_frame.selection().selection().visibleEnd()) && 
1610         baseWritingDirectionForSelectionStart() == direction)
1611         return;
1612 #endif
1613         
1614     Element* focusedElement = document().focusedElement();
1615     if (is<HTMLTextFormControlElement>(focusedElement)) {
1616         if (direction == NaturalWritingDirection)
1617             return;
1618         downcast<HTMLTextFormControlElement>(*focusedElement).setAttribute(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
1619         focusedElement->dispatchInputEvent();
1620         document().updateStyleIfNeeded();
1621         return;
1622     }
1623
1624     RefPtr<MutableStyleProperties> style = MutableStyleProperties::create();
1625     style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
1626     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
1627 }
1628
1629 WritingDirection Editor::baseWritingDirectionForSelectionStart() const
1630 {
1631     WritingDirection result = LeftToRightWritingDirection;
1632
1633     Position pos = m_frame.selection().selection().visibleStart().deepEquivalent();
1634     Node* node = pos.deprecatedNode();
1635     if (!node)
1636         return result;
1637
1638     auto renderer = node->renderer();
1639     if (!renderer)
1640         return result;
1641
1642     if (!renderer->isRenderBlockFlow()) {
1643         renderer = renderer->containingBlock();
1644         if (!renderer)
1645             return result;
1646     }
1647
1648     switch (renderer->style().direction()) {
1649     case LTR:
1650         return LeftToRightWritingDirection;
1651     case RTL:
1652         return RightToLeftWritingDirection;
1653     }
1654     
1655     return result;
1656 }
1657
1658 void Editor::selectComposition()
1659 {
1660     RefPtr<Range> range = compositionRange();
1661     if (!range)
1662         return;
1663     
1664     // The composition can start inside a composed character sequence, so we have to override checks.
1665     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
1666     VisibleSelection selection;
1667     selection.setWithoutValidation(range->startPosition(), range->endPosition());
1668     m_frame.selection().setSelection(selection, 0);
1669 }
1670
1671 void Editor::confirmComposition()
1672 {
1673     if (!m_compositionNode)
1674         return;
1675     setComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
1676 }
1677
1678 void Editor::cancelComposition()
1679 {
1680     if (!m_compositionNode)
1681         return;
1682     setComposition(emptyString(), CancelComposition);
1683 }
1684
1685 bool Editor::cancelCompositionIfSelectionIsInvalid()
1686 {
1687     unsigned start;
1688     unsigned end;
1689     if (!hasComposition() || ignoreCompositionSelectionChange() || getCompositionSelection(start, end))
1690         return false;
1691
1692     cancelComposition();
1693     return true;
1694 }
1695
1696 void Editor::confirmComposition(const String& text)
1697 {
1698     setComposition(text, ConfirmComposition);
1699 }
1700
1701 void Editor::setComposition(const String& text, SetCompositionMode mode)
1702 {
1703     ASSERT(mode == ConfirmComposition || mode == CancelComposition);
1704     UserTypingGestureIndicator typingGestureIndicator(m_frame);
1705
1706     setIgnoreCompositionSelectionChange(true);
1707
1708     if (mode == CancelComposition)
1709         ASSERT(text == emptyString());
1710     else
1711         selectComposition();
1712
1713     if (m_frame.selection().isNone()) {
1714         setIgnoreCompositionSelectionChange(false);
1715         return;
1716     }
1717     
1718     // Dispatch a compositionend event to the focused node.
1719     // We should send this event before sending a TextEvent as written in Section 6.2.2 and 6.2.3 of
1720     // the DOM Event specification.
1721     if (Element* target = document().focusedElement()) {
1722         Ref<CompositionEvent> event = CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text);
1723         target->dispatchEvent(event);
1724     }
1725
1726     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
1727     // will delete the old composition with an optimized replace operation.
1728     if (text.isEmpty() && mode != CancelComposition)
1729         TypingCommand::deleteSelection(document(), 0);
1730
1731     m_compositionNode = nullptr;
1732     m_customCompositionUnderlines.clear();
1733
1734     insertTextForConfirmedComposition(text);
1735
1736     if (mode == CancelComposition) {
1737         // An open typing command that disagrees about current selection would cause issues with typing later on.
1738         TypingCommand::closeTyping(&m_frame);
1739     }
1740
1741     setIgnoreCompositionSelectionChange(false);
1742 }
1743
1744 void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
1745 {
1746     UserTypingGestureIndicator typingGestureIndicator(m_frame);
1747
1748     setIgnoreCompositionSelectionChange(true);
1749
1750     // Updates styles before setting selection for composition to prevent
1751     // inserting the previous composition text into text nodes oddly.
1752     // See https://bugs.webkit.org/show_bug.cgi?id=46868
1753     document().updateStyleIfNeeded();
1754
1755     selectComposition();
1756
1757     if (m_frame.selection().isNone()) {
1758         setIgnoreCompositionSelectionChange(false);
1759         return;
1760     }
1761
1762 #if PLATFORM(IOS)
1763     client()->startDelayingAndCoalescingContentChangeNotifications();
1764 #endif
1765
1766     Element* target = document().focusedElement();
1767     if (target) {
1768         // Dispatch an appropriate composition event to the focused node.
1769         // We check the composition status and choose an appropriate composition event since this
1770         // function is used for three purposes:
1771         // 1. Starting a new composition.
1772         //    Send a compositionstart and a compositionupdate event when this function creates
1773         //    a new composition node, i.e.
1774         //    m_compositionNode == 0 && !text.isEmpty().
1775         //    Sending a compositionupdate event at this time ensures that at least one
1776         //    compositionupdate event is dispatched.
1777         // 2. Updating the existing composition node.
1778         //    Send a compositionupdate event when this function updates the existing composition
1779         //    node, i.e. m_compositionNode != 0 && !text.isEmpty().
1780         // 3. Canceling the ongoing composition.
1781         //    Send a compositionend event when function deletes the existing composition node, i.e.
1782         //    m_compositionNode != 0 && test.isEmpty().
1783         RefPtr<CompositionEvent> event;
1784         if (!m_compositionNode) {
1785             // We should send a compositionstart event only when the given text is not empty because this
1786             // function doesn't create a composition node when the text is empty.
1787             if (!text.isEmpty()) {
1788                 target->dispatchEvent(CompositionEvent::create(eventNames().compositionstartEvent, document().domWindow(), selectedText()));
1789                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1790             }
1791         } else {
1792             if (!text.isEmpty())
1793                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1794             else
1795                 event = CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text);
1796         }
1797         if (event)
1798             target->dispatchEvent(*event);
1799     }
1800
1801     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
1802     // will delete the old composition with an optimized replace operation.
1803     if (text.isEmpty())
1804         TypingCommand::deleteSelection(document(), TypingCommand::PreventSpellChecking);
1805
1806     m_compositionNode = nullptr;
1807     m_customCompositionUnderlines.clear();
1808
1809     if (!text.isEmpty()) {
1810         TypingCommand::insertText(document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionUpdate);
1811
1812         // Find out what node has the composition now.
1813         Position base = m_frame.selection().selection().base().downstream();
1814         Position extent = m_frame.selection().selection().extent();
1815         Node* baseNode = base.deprecatedNode();
1816         unsigned baseOffset = base.deprecatedEditingOffset();
1817         Node* extentNode = extent.deprecatedNode();
1818         unsigned extentOffset = extent.deprecatedEditingOffset();
1819
1820         if (is<Text>(baseNode) && baseNode == extentNode && baseOffset + text.length() == extentOffset) {
1821             m_compositionNode = downcast<Text>(baseNode);
1822             m_compositionStart = baseOffset;
1823             m_compositionEnd = extentOffset;
1824             m_customCompositionUnderlines = underlines;
1825             for (auto& underline : m_customCompositionUnderlines) {
1826                 underline.startOffset += baseOffset;
1827                 underline.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 = VisiblePosition(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())
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();
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();
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();
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();
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.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.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             for (auto& detail : results[i].details) {
2501                 ASSERT(detail.length > 0 && detail.location >= 0);
2502                 if (paragraph.checkingRangeCovers(resultLocation + detail.location, detail.length)) {
2503                     RefPtr<Range> badGrammarRange = paragraph.subrange(resultLocation + detail.location, detail.length);
2504                     badGrammarRange->startContainer().document().markers().addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail.userDescription);
2505                 }
2506             }
2507         } else if (resultEndLocation <= spellingRangeEndOffset && resultEndLocation >= paragraph.checkingStart()
2508             && isAutomaticTextReplacementType(resultType)) {
2509             // In this case the result range just has to touch the spelling range, so we can handle replacing non-word text such as punctuation.
2510             ASSERT(resultLength > 0 && resultLocation >= 0);
2511
2512             if (shouldShowCorrectionPanel && (resultEndLocation < spellingRangeEndOffset
2513                 || !(resultType & (TextCheckingTypeReplacement | TextCheckingTypeCorrection))))
2514                 continue;
2515
2516             // Apply replacement if:
2517             // 1. The replacement length is non-zero.
2518             // 2. The result doesn't end at an ambiguous boundary.
2519             //    (FIXME: this is required until 6853027 is fixed and text checking can do this for us
2520             bool doReplacement = replacement.length() > 0 && !resultEndsAtAmbiguousBoundary;
2521             RefPtr<Range> rangeToReplace = paragraph.subrange(resultLocation, resultLength);
2522
2523             // adding links should be done only immediately after they are typed
2524             if (resultType == TextCheckingTypeLink && selectionOffset != resultEndLocation + 1)
2525                 continue;
2526
2527             if (!(shouldPerformReplacement || shouldCheckForCorrection || shouldMarkLink) || !doReplacement)
2528                 continue;
2529
2530             String replacedString = plainText(rangeToReplace.get());
2531             const bool existingMarkersPermitReplacement = m_alternativeTextController->processMarkersOnTextToBeReplacedByResult(&results[i], rangeToReplace.get(), replacedString);
2532             if (!existingMarkersPermitReplacement)
2533                 continue;
2534
2535             if (shouldShowCorrectionPanel) {
2536                 if (resultEndLocation == spellingRangeEndOffset) {
2537                     // We only show the correction panel on the last word.
2538                     m_alternativeTextController->show(rangeToReplace, replacement);
2539                     break;
2540                 }
2541                 // If this function is called for showing correction panel, we ignore other correction or replacement.
2542                 continue;
2543             }
2544
2545             VisibleSelection selectionToReplace(*rangeToReplace, DOWNSTREAM);
2546             if (selectionToReplace != m_frame.selection().selection()) {
2547                 if (!m_frame.selection().shouldChangeSelection(selectionToReplace))
2548                     continue;
2549             }
2550
2551             if (resultType == TextCheckingTypeLink) {
2552                 m_frame.selection().setSelection(selectionToReplace);
2553                 selectionChanged = true;
2554                 restoreSelectionAfterChange = false;
2555                 if (canEditRichly())
2556                     applyCommand(CreateLinkCommand::create(document(), replacement));
2557             } else if (canEdit() && shouldInsertText(replacement, rangeToReplace.get(), EditorInsertActionTyped)) {
2558                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, resultLocation, resultLength);
2559
2560                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
2561                     if (Element* root = m_frame.selection().selection().rootEditableElement())
2562                         cache->postNotification(root, AXObjectCache::AXAutocorrectionOccured);
2563                 }
2564
2565                 // Skip all other results for the replaced text.
2566                 while (i + 1 < results.size() && results[i + 1].location + offsetDueToReplacement <= resultLocation)
2567                     i++;
2568
2569                 selectionChanged = true;
2570                 offsetDueToReplacement += replacement.length() - resultLength;
2571                 if (resultLocation < selectionOffset)
2572                     selectionOffset += replacement.length() - resultLength;
2573
2574                 // Add a marker so that corrections can easily be undone and won't be re-corrected.
2575                 if (resultType == TextCheckingTypeCorrection)
2576                     m_alternativeTextController->markCorrection(paragraph.subrange(resultLocation, replacement.length()), replacedString);
2577             }
2578         }
2579     }
2580
2581     if (selectionChanged) {
2582         TextCheckingParagraph extendedParagraph(paragraph);
2583         // Restore the caret position if we have made any replacements
2584         extendedParagraph.expandRangeToNextEnd();
2585         if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffset <= extendedParagraph.rangeLength()) {
2586             RefPtr<Range> selectionRange = extendedParagraph.subrange(0, selectionOffset);
2587             m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
2588             if (adjustSelectionForParagraphBoundaries)
2589                 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2590         } else {
2591             // If this fails for any reason, the fallback is to go one position beyond the last replacement
2592             m_frame.selection().moveTo(m_frame.selection().selection().end());
2593             m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2594         }
2595     }
2596 }
2597
2598 void Editor::changeBackToReplacedString(const String& replacedString)
2599 {
2600 #if !PLATFORM(IOS)
2601     ASSERT(unifiedTextCheckerEnabled());
2602
2603     if (replacedString.isEmpty())
2604         return;
2605
2606     RefPtr<Range> selection = selectedRange();
2607     if (!shouldInsertText(replacedString, selection.get(), EditorInsertActionPasted))
2608         return;
2609     
2610     m_alternativeTextController->recordAutocorrectionResponseReversed(replacedString, selection);
2611     TextCheckingParagraph paragraph(selection);
2612     replaceSelectionWithText(replacedString, false, false, EditActionInsert);
2613     RefPtr<Range> changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
2614     changedRange->startContainer().document().markers().addMarker(changedRange.get(), DocumentMarker::Replacement, String());
2615     m_alternativeTextController->markReversed(changedRange.get());
2616 #else
2617     ASSERT_NOT_REACHED();
2618     UNUSED_PARAM(replacedString);
2619 #endif // !PLATFORM(IOS)
2620 }
2621
2622
2623 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection)
2624 {
2625     if (unifiedTextCheckerEnabled()) {
2626         if (!isContinuousSpellCheckingEnabled())
2627             return;
2628
2629         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
2630         TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling;
2631         if (markGrammar && isGrammarCheckingEnabled())
2632             textCheckingOptions |= TextCheckingTypeGrammar;
2633         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedRange().get(), grammarSelection.toNormalizedRange().get());
2634         return;
2635     }
2636
2637     RefPtr<Range> firstMisspellingRange;
2638     markMisspellings(spellingSelection, firstMisspellingRange);
2639     if (markGrammar)
2640         markBadGrammar(grammarSelection);
2641 }
2642
2643 void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
2644 {
2645     m_alternativeTextController->respondToUnappliedSpellCorrection(selectionOfCorrected, corrected, correction);
2646 }
2647
2648 void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
2649 {
2650     if (!document().markers().hasMarkers())
2651         return;
2652
2653     if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)))
2654         return;
2655
2656     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
2657     // several scenarios:
2658     // 1. Insert in the middle of a word.
2659     // 2. Appending non whitespace at the beginning of word.
2660     // 3. Appending non whitespace at the end of word.
2661     // Note that, appending only whitespaces at the beginning or end of word won't change the word, so we don't need to
2662     // remove the markers on that word.
2663     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
2664     // selection, and remove words between the selection boundaries.
2665     //
2666     VisiblePosition startOfSelection = m_frame.selection().selection().start();
2667     VisiblePosition endOfSelection = m_frame.selection().selection().end();
2668     if (startOfSelection.isNull())
2669         return;
2670     // First word is the word that ends after or on the start of selection.
2671     VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfOnBoundary);
2672     VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBoundary);
2673     // Last word is the word that begins before or on the end of selection
2674     VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnBoundary);
2675     VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBoundary);
2676
2677     if (startOfFirstWord.isNull()) {
2678         startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary);
2679         endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary);
2680     }
2681     
2682     if (endOfLastWord.isNull()) {
2683         startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary);
2684         endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary);
2685     }
2686
2687     // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the start of selection,
2688     // we choose next word as the first word.
2689     if (doNotRemoveIfSelectionAtWordBoundary && endOfFirstWord == startOfSelection) {
2690         startOfFirstWord = nextWordPosition(startOfFirstWord);
2691         endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary);
2692         if (startOfFirstWord == endOfSelection)
2693             return;
2694     }
2695
2696     // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at the end of selection,
2697     // we choose previous word as the last word.
2698     if (doNotRemoveIfSelectionAtWordBoundary && startOfLastWord == endOfSelection) {
2699         startOfLastWord = previousWordPosition(startOfLastWord);
2700         endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary);
2701         if (endOfLastWord == startOfSelection)
2702             return;
2703     }
2704
2705     if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull())
2706         return;
2707
2708     // Now we remove markers on everything between startOfFirstWord and endOfLastWord.
2709     // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the
2710     // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant
2711     // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde,
2712     // we would like to remove the marker from word "avant" and whitespace as well. So we need to get the continous range of
2713     // of marker that contains the word in question, and remove marker on that whole range.
2714     RefPtr<Range> wordRange = Range::create(document(), startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
2715
2716     Vector<RenderedDocumentMarker*> markers = document().markers().markersInRange(wordRange.get(), DocumentMarker::DictationAlternatives);
2717     for (auto* marker : markers)
2718         m_alternativeTextController->removeDictationAlternativesForMarker(marker);
2719
2720 #if PLATFORM(IOS)
2721     document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::CorrectionIndicator | DocumentMarker::SpellCheckingExemption | DocumentMarker::DictationAlternatives | DocumentMarker::DictationPhraseWithAlternatives, DocumentMarkerController::RemovePartiallyOverlappingMarker);
2722 #else
2723     document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::Grammar | DocumentMarker::CorrectionIndicator | DocumentMarker::SpellCheckingExemption | DocumentMarker::DictationAlternatives, DocumentMarkerController::RemovePartiallyOverlappingMarker);
2724 #endif
2725     document().markers().clearDescriptionOnMarkersIntersectingRange(wordRange.get(), DocumentMarker::Replacement);
2726 }
2727
2728 void Editor::deletedAutocorrectionAtPosition(const Position& position, const String& originalString)
2729 {
2730     m_alternativeTextController->deletedAutocorrectionAtPosition(position, originalString);
2731 }
2732
2733 PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
2734 {
2735     Document* document = m_frame.documentAtPoint(windowPoint);
2736     if (!document)
2737         return 0;
2738     
2739     Frame* frame = document->frame();
2740     ASSERT(frame);
2741     FrameView* frameView = frame->view();
2742     if (!frameView)
2743         return 0;
2744     IntPoint framePoint = frameView->windowToContents(windowPoint);
2745     VisibleSelection selection(frame->visiblePositionForPoint(framePoint));
2746
2747     return selection.toNormalizedRange();
2748 }
2749
2750 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2751 {
2752     if (m_ignoreCompositionSelectionChange)
2753         return;
2754
2755     m_frame.selection().revealSelection(alignment, revealExtentOption);
2756 }
2757
2758 void Editor::setIgnoreCompositionSelectionChange(bool ignore, RevealSelection shouldRevealExistingSelection)
2759 {
2760     if (m_ignoreCompositionSelectionChange == ignore)
2761         return;
2762
2763     m_ignoreCompositionSelectionChange = ignore;
2764 #if PLATFORM(IOS)
2765     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
2766     if (!ignore)
2767         respondToChangedSelection(m_frame.selection().selection(), 0);
2768 #endif
2769     if (!ignore && shouldRevealExistingSelection == RevealSelection::Yes)
2770         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
2771 }
2772
2773 PassRefPtr<Range> Editor::compositionRange() const
2774 {
2775     if (!m_compositionNode)
2776         return 0;
2777     unsigned length = m_compositionNode->length();
2778     unsigned start = std::min(m_compositionStart, length);
2779     unsigned end = std::min(std::max(start, m_compositionEnd), length);
2780     if (start >= end)
2781         return 0;
2782     return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
2783 }
2784
2785 bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
2786 {
2787     if (!m_compositionNode)
2788         return false;
2789     const VisibleSelection& selection = m_frame.selection().selection();
2790     Position start = selection.start();
2791     if (start.deprecatedNode() != m_compositionNode)
2792         return false;
2793     Position end = selection.end();
2794     if (end.deprecatedNode() != m_compositionNode)
2795         return false;
2796
2797     if (static_cast<unsigned>(start.deprecatedEditingOffset()) < m_compositionStart)
2798         return false;
2799     if (static_cast<unsigned>(end.deprecatedEditingOffset()) > m_compositionEnd)
2800         return false;
2801
2802     selectionStart = start.deprecatedEditingOffset() - m_compositionStart;
2803     selectionEnd = start.deprecatedEditingOffset() - m_compositionEnd;
2804     return true;
2805 }
2806
2807 void Editor::transpose()
2808 {
2809     if (!canEdit())
2810         return;
2811
2812     VisibleSelection selection = m_frame.selection().selection();
2813     if (!selection.isCaret())
2814         return;
2815
2816     // Make a selection that goes back one character and forward two characters.
2817     VisiblePosition caret = selection.visibleStart();
2818     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
2819     VisiblePosition previous = next.previous();
2820     if (next == previous)
2821         return;
2822     previous = previous.previous();
2823     if (!inSameParagraph(next, previous))
2824         return;
2825     RefPtr<Range> range = makeRange(previous, next);
2826     if (!range)
2827         return;
2828     VisibleSelection newSelection(*range, DOWNSTREAM);
2829
2830     // Transpose the two characters.
2831     String text = plainText(range.get());
2832     if (text.length() != 2)
2833         return;
2834     String transposed = text.right(1) + text.left(1);
2835
2836     // Select the two characters.
2837     if (newSelection != m_frame.selection().selection()) {
2838         if (!m_frame.selection().shouldChangeSelection(newSelection))
2839             return;
2840         m_frame.selection().setSelection(newSelection);
2841     }
2842
2843     // Insert the transposed characters.
2844     if (!shouldInsertText(transposed, range.get(), EditorInsertActionTyped))
2845         return;
2846     replaceSelectionWithText(transposed, false, false, EditActionInsert);
2847 }
2848
2849 void Editor::addRangeToKillRing(const Range& range, KillRingInsertionMode mode)
2850 {
2851     addTextToKillRing(plainText(&range), mode);
2852 }
2853
2854 void Editor::addTextToKillRing(const String& text, KillRingInsertionMode mode)
2855 {
2856     if (m_shouldStartNewKillRingSequence)
2857         killRing().startNewSequence();
2858
2859     m_shouldStartNewKillRingSequence = false;
2860
2861     // If the kill was from a backwards motion, prepend to the kill ring.
2862     // This will ensure that alternating forward and backward kills will
2863     // build up the original string in the kill ring without permuting it.
2864     switch (mode) {
2865     case KillRingInsertionMode::PrependText:
2866         killRing().prepend(text);
2867         break;
2868     case KillRingInsertionMode::AppendText:
2869         killRing().append(text);
2870         break;
2871     }
2872 }
2873
2874 void Editor::startAlternativeTextUITimer()
2875 {
2876     m_alternativeTextController->startAlternativeTextUITimer(AlternativeTextTypeCorrection);
2877 }
2878
2879 void Editor::handleAlternativeTextUIResult(const String& correction)
2880 {
2881     m_alternativeTextController->handleAlternativeTextUIResult(correction);
2882 }
2883
2884
2885 void Editor::dismissCorrectionPanelAsIgnored()
2886 {
2887     m_alternativeTextController->dismiss(ReasonForDismissingAlternativeTextIgnored);
2888 }
2889
2890 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions options, AXTextStateChangeIntent intent)
2891 {
2892     // If the new selection is orphaned, then don't update the selection.
2893     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
2894         return;
2895
2896     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
2897     // because there is work that it must do in this situation.
2898     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
2899     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
2900     bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
2901     if (selectionDidNotChangeDOMPosition || m_frame.selection().shouldChangeSelection(newSelection))
2902         m_frame.selection().setSelection(newSelection, options, intent);
2903
2904     // Some editing operations change the selection visually without affecting its position within the DOM.
2905     // For example when you press return in the following (the caret is marked by ^):
2906     // <div contentEditable="true"><div>^Hello</div></div>
2907     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
2908     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
2909     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
2910     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
2911 #if PLATFORM(IOS)
2912     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830>
2913     if (m_ignoreCompositionSelectionChange)
2914         return;
2915 #endif
2916     if (selectionDidNotChangeDOMPosition && client())
2917         client()->respondToChangedSelection(&m_frame);
2918 }
2919
2920 String Editor::selectedText() const
2921 {
2922     return selectedText(TextIteratorDefaultBehavior);
2923 }
2924
2925 String Editor::selectedTextForDataTransfer() const
2926 {
2927     if (m_frame.settings().selectionIncludesAltImageText())
2928         return selectedText(TextIteratorEmitsImageAltText);
2929     return selectedText();
2930 }
2931
2932 String Editor::selectedText(TextIteratorBehavior behavior) const
2933 {
2934     // We remove '\0' characters because they are not visibly rendered to the user.
2935     return plainText(m_frame.selection().toNormalizedRange().get(), behavior).replaceWithLiteral('\0', "");
2936 }
2937
2938 static inline void collapseCaretWidth(IntRect& rect)
2939 {
2940     // FIXME: Width adjustment doesn't work for rotated text.
2941     if (rect.width() == caretWidth)
2942         rect.setWidth(0);
2943     else if (rect.height() == caretWidth)
2944         rect.setHeight(0);
2945 }
2946
2947 IntRect Editor::firstRectForRange(Range* range) const
2948 {
2949     VisiblePosition startVisiblePosition(range->startPosition(), DOWNSTREAM);
2950
2951     if (range->collapsed()) {
2952         // FIXME: Getting caret rect and removing caret width is a very roundabout way to get collapsed range location.
2953         // In particular, width adjustment doesn't work for rotated text.
2954         IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect();
2955         collapseCaretWidth(startCaretRect);
2956         return startCaretRect;
2957     }
2958
2959     VisiblePosition endVisiblePosition(range->endPosition(), UPSTREAM);
2960
2961     if (inSameLine(startVisiblePosition, endVisiblePosition))
2962         return enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(range));
2963
2964     LayoutUnit extraWidthToEndOfLine = 0;
2965     IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect(&extraWidthToEndOfLine);
2966     if (startCaretRect == IntRect())
2967         return IntRect();
2968
2969     // When start and end aren't on the same line, we want to go from start to the end of its line.
2970     bool textIsHorizontal = startCaretRect.width() == caretWidth;
2971     return textIsHorizontal ?
2972         IntRect(startCaretRect.x(),
2973             startCaretRect.y(),
2974             startCaretRect.width() + extraWidthToEndOfLine,
2975             startCaretRect.height()) :
2976         IntRect(startCaretRect.x(),
2977             startCaretRect.y(),
2978             startCaretRect.width(),
2979             startCaretRect.height() + extraWidthToEndOfLine);
2980 }
2981
2982 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
2983 {
2984 #if PLATFORM(IOS)
2985     if (m_frame.selectionChangeCallbacksDisabled())
2986         return true;
2987 #endif
2988     return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting);
2989 }
2990
2991 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
2992 {
2993     if (style.isEmpty()) {
2994         m_frame.selection().clearTypingStyle();
2995         return;
2996     }
2997
2998     // Calculate the current typing style.
2999     RefPtr<EditingStyle> typingStyle;
3000     if (auto existingTypingStyle = m_frame.selection().typingStyle())
3001         typingStyle = existingTypingStyle->copy();
3002     else
3003         typingStyle = EditingStyle::create();
3004     typingStyle->overrideTypingStyleAt(style, m_frame.selection().selection().visibleStart().deepEquivalent());
3005
3006     // Handle block styles, substracting these from the typing style.
3007     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
3008     if (!blockStyle->isEmpty())
3009         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
3010
3011     // Set the remaining style as the typing style.
3012     m_frame.selection().setTypingStyle(typingStyle);
3013 }
3014
3015 void Editor::computeAndSetTypingStyle(StyleProperties& properties, EditAction editingAction)
3016 {
3017     return computeAndSetTypingStyle(EditingStyle::create(&properties), editingAction);
3018 }
3019
3020 void Editor::textFieldDidBeginEditing(Element* e)
3021 {
3022     if (client())
3023         client()->textFieldDidBeginEditing(e);
3024 }
3025
3026 void Editor::textFieldDidEndEditing(Element* e)
3027 {
3028     dismissCorrectionPanelAsIgnored();
3029     if (client())
3030         client()->textFieldDidEndEditing(e);
3031 }
3032
3033 void Editor::textDidChangeInTextField(Element* e)
3034 {
3035     if (client())
3036         client()->textDidChangeInTextField(e);
3037 }
3038
3039 bool Editor::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
3040 {
3041     if (client())
3042         return client()->doTextFieldCommandFromEvent(e, ke);
3043
3044     return false;
3045 }
3046
3047 void Editor::textWillBeDeletedInTextField(Element* input)
3048 {
3049     if (client())
3050         client()->textWillBeDeletedInTextField(input);
3051 }
3052
3053 void Editor::textDidChangeInTextArea(Element* e)
3054 {
3055     if (client())
3056         client()->textDidChangeInTextArea(e);
3057 }
3058
3059 void Editor::applyEditingStyleToBodyElement() const
3060 {
3061     auto collection = document().getElementsByTagName(HTMLNames::bodyTag.localName());
3062     unsigned length = collection->length();
3063     for (unsigned i = 0; i < length; ++i)
3064         applyEditingStyleToElement(collection->item(i));
3065 }
3066
3067 void Editor::applyEditingStyleToElement(Element* element) const
3068 {
3069     ASSERT(!element || is<StyledElement>(*element));
3070     if (!is<StyledElement>(element))
3071         return;
3072
3073     // Mutate using the CSSOM wrapper so we get the same event behavior as a script.
3074     CSSStyleDeclaration* style = downcast<StyledElement>(*element).style();
3075     style->setPropertyInternal(CSSPropertyWordWrap, "break-word", false, IGNORE_EXCEPTION);
3076     style->setPropertyInternal(CSSPropertyWebkitNbspMode, "space", false, IGNORE_EXCEPTION);
3077     style->setPropertyInternal(CSSPropertyWebkitLineBreak, "after-white-space", false, IGNORE_EXCEPTION);
3078 }
3079
3080 bool Editor::findString(const String& target, FindOptions options)
3081 {
3082     VisibleSelection selection = m_frame.selection().selection();
3083
3084     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
3085
3086     if (!resultRange)
3087         return false;
3088
3089     m_frame.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
3090
3091     if (!(options & DoNotRevealSelection))
3092         m_frame.selection().revealSelection();
3093
3094     return true;
3095 }
3096
3097 PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
3098 {
3099     RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
3100     if (!nextMatch)
3101         return 0;
3102
3103     nextMatch->firstNode()->renderer()->scrollRectToVisible(nextMatch->absoluteBoundingBox(),
3104         ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
3105
3106     return nextMatch.release();
3107 }
3108
3109 PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
3110 {
3111     if (target.isEmpty())
3112         return 0;
3113
3114     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
3115     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
3116     RefPtr<Range> searchRange(rangeOfContents(document()));
3117
3118     bool forward = !(options & Backwards);
3119     bool startInReferenceRange = referenceRange && (options & StartInSelection);
3120     if (referenceRange) {
3121         if (forward)
3122             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
3123         else
3124             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
3125     }
3126
3127     RefPtr<Node> shadowTreeRoot = referenceRange ? referenceRange->startContainer().nonBoundaryShadowTreeRootNode() : nullptr;
3128     if (shadowTreeRoot) {
3129         if (forward)
3130             searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->countChildNodes());
3131         else
3132             searchRange->setStart(shadowTreeRoot.get(), 0);
3133     }
3134
3135     RefPtr<Range> resultRange(findPlainText(*searchRange, target, options));
3136     // If we started in the reference range and the found range exactly matches the reference range, find again.
3137     // Build a selection with the found range to remove collapsed whitespace.
3138     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3139     if (startInReferenceRange && areRangesEqual(VisibleSelection(*resultRange).toNormalizedRange().get(), referenceRange)) {
3140         searchRange = rangeOfContents(document());
3141         if (forward)
3142             searchRange->setStart(referenceRange->endPosition());
3143         else
3144             searchRange->setEnd(referenceRange->startPosition());
3145
3146         if (shadowTreeRoot) {
3147             if (forward)
3148                 searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->countChildNodes());
3149             else
3150                 searchRange->setStart(shadowTreeRoot.get(), 0);
3151         }
3152
3153         resultRange = findPlainText(*searchRange, target, options);
3154     }
3155
3156     // If nothing was found in the shadow tree, search in main content following the shadow tree.
3157     if (resultRange->collapsed() && shadowTreeRoot) {
3158         searchRange = rangeOfContents(document());
3159         if (forward)
3160             searchRange->setStartAfter(shadowTreeRoot->shadowHost());
3161         else
3162             searchRange->setEndBefore(shadowTreeRoot->shadowHost());
3163
3164         resultRange = findPlainText(*searchRange, target, options);
3165     }
3166
3167     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3168     // redundantly re-search the area already searched in some cases).
3169     if (resultRange->collapsed() && options & WrapAround) {
3170         searchRange = rangeOfContents(document());
3171         resultRange = findPlainText(*searchRange, target, options);
3172         // We used to return false here if we ended up with the same range that we started with
3173         // (e.g., the reference range was already the only instance of this text). But we decided that
3174         // this should be a success case instead, so we'll just fall through in that case.
3175     }
3176
3177     return resultRange->collapsed() ? nullptr : resultRange.release();
3178 }
3179
3180 static bool isFrameInRange(Frame* frame, Range* range)
3181 {
3182     bool inRange = false;
3183     for (HTMLFrameOwnerElement* ownerElement = frame->ownerElement(); ownerElement; ownerElement = ownerElement->document().ownerElement()) {
3184         if (&ownerElement->document() == &range->ownerDocument()) {
3185             inRange = range->intersectsNode(ownerElement, IGNORE_EXCEPTION);
3186             break;
3187         }
3188     }
3189     return inRange;
3190 }
3191
3192 unsigned Editor::countMatchesForText(const String& target, Range* range, FindOptions options, unsigned limit, bool markMatches, Vector<RefPtr<Range>>* matches)
3193 {
3194     if (target.isEmpty())
3195         return 0;
3196
3197     RefPtr<Range> searchRange;
3198     if (range) {
3199         if (&range->ownerDocument() == &document())
3200             searchRange = range;
3201         else if (!isFrameInRange(&m_frame, range))
3202             return 0;
3203     }
3204     if (!searchRange)
3205         searchRange = rangeOfContents(document());
3206
3207     Node& originalEndContainer = searchRange->endContainer();
3208     int originalEndOffset = searchRange->endOffset();
3209
3210     unsigned matchCount = 0;
3211     do {
3212         RefPtr<Range> resultRange(findPlainText(*searchRange, target, options & ~Backwards));
3213         if (resultRange->collapsed()) {
3214             if (!resultRange->startContainer().isInShadowTree())
3215                 break;
3216
3217             searchRange->setStartAfter(resultRange->startContainer().shadowHost(), IGNORE_EXCEPTION);
3218             searchRange->setEnd(&originalEndContainer, originalEndOffset, IGNORE_EXCEPTION);
3219             continue;
3220         }
3221
3222         ++matchCount;
3223         if (matches)
3224             matches->append(resultRange);
3225         
3226         if (markMatches)
3227             document().markers().addMarker(resultRange.get(), DocumentMarker::TextMatch);
3228
3229         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
3230         if (limit > 0 && matchCount >= limit)
3231             break;
3232
3233         // Set the new start for the search range to be the end of the previous
3234         // result range. There is no need to use a VisiblePosition here,
3235         // since findPlainText will use a TextIterator to go over the visible
3236         // text nodes. 
3237         searchRange->setStart(&resultRange->endContainer(), resultRange->endOffset(), IGNORE_EXCEPTION);
3238
3239         Node* shadowTreeRoot = searchRange->shadowRoot();
3240         if (searchRange->collapsed() && shadowTreeRoot)
3241             searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->countChildNodes(), IGNORE_EXCEPTION);
3242     } while (true);
3243
3244     return matchCount;
3245 }
3246
3247 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
3248 {
3249     if (flag == m_areMarkedTextMatchesHighlighted)
3250         return;
3251
3252     m_areMarkedTextMatchesHighlighted = flag;
3253     document().markers().repaintMarkers(DocumentMarker::TextMatch);
3254 }
3255
3256 void Editor::respondToChangedSelection(const VisibleSelection&, FrameSelection::SetSelectionOptions options)
3257 {
3258 #if PLATFORM(IOS)
3259     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
3260     if (m_ignoreCompositionSelectionChange)
3261         return;
3262 #endif
3263
3264     if (client())
3265         client()->respondToChangedSelection(&m_frame);
3266
3267 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
3268     if (client() && canEdit())
3269         client()->requestCandidatesForSelection(m_frame.selection().selection());
3270 #endif
3271
3272 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3273     if (shouldDetectTelephoneNumbers())
3274         m_telephoneNumberDetectionUpdateTimer.startOneShot(0);
3275 #endif
3276
3277     setStartNewKillRingSequence(true);
3278
3279     if (m_editorUIUpdateTimer.isActive())
3280         return;
3281
3282     // Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
3283     m_editorUIUpdateTimerShouldCheckSpellingAndGrammar = options & FrameSelection::CloseTyping
3284         && !(options & FrameSelection::SpellCorrectionTriggered);
3285     m_editorUIUpdateTimerWasTriggeredByDictation = options & FrameSelection::DictationTriggered;
3286     m_editorUIUpdateTimer.startOneShot(0);
3287 }
3288
3289 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3290
3291 bool Editor::shouldDetectTelephoneNumbers()
3292 {
3293     if (!m_frame.document())
3294         return false;
3295     return document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
3296 }
3297
3298 void Editor::scanSelectionForTelephoneNumbers()
3299 {
3300     if (!shouldDetectTelephoneNumbers() || !client())
3301         return;
3302
3303     m_detectedTelephoneNumberRanges.clear();
3304
3305     Vector<RefPtr<Range>> markedRanges;
3306
3307     FrameSelection& frameSelection = m_frame.selection();
3308     if (!frameSelection.isRange()) {
3309         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3310         return;
3311     }
3312     RefPtr<Range> selectedRange = frameSelection.toNormalizedRange();
3313
3314     // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
3315     static const int charactersToExtend = 15;
3316     const VisibleSelection& visibleSelection = frameSelection.selection();
3317     Position start = visibleSelection.start();
3318     Position end = visibleSelection.end();
3319     for (int i = 0; i < charactersToExtend; ++i) {
3320         start = start.previous(Character);
3321         end = end.next(Character);
3322     }
3323
3324     FrameSelection extendedSelection;
3325     extendedSelection.setStart(start);
3326     extendedSelection.setEnd(end);
3327     RefPtr<Range> extendedRange = extendedSelection.toNormalizedRange();
3328
3329     if (!extendedRange) {
3330         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3331         return;
3332     }
3333
3334     scanRangeForTelephoneNumbers(*extendedRange, extendedRange->text(), markedRanges);
3335
3336     // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
3337     for (auto& range : markedRanges) {
3338         if (rangesOverlap(range.get(), selectedRange.get()))
3339             m_detectedTelephoneNumberRanges.append(range);
3340     }
3341
3342     m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3343 }
3344
3345 void Editor::scanRangeForTelephoneNumbers(Range& range, const StringView& stringView, Vector<RefPtr<Range>>& markedRanges)
3346 {
3347     // Don't scan for phone numbers inside editable regions.
3348     Node& startNode = range.startContainer();
3349     if (startNode.hasEditableStyle())
3350         return;
3351
3352     // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
3353     // relative to the scannerPosition
3354     unsigned length = stringView.length();
3355     unsigned scannerPosition = 0;
3356     int relativeStartPosition = 0;
3357     int relativeEndPosition = 0;
3358
3359     auto characters = stringView.upconvertedCharacters();
3360
3361     while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
3362         // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
3363         // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So subtract 1 to get the same
3364         // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
3365         // to the old parser).
3366         --relativeEndPosition;
3367
3368         ASSERT(scannerPosition + relativeEndPosition < length);
3369
3370         unsigned subrangeOffset = scannerPosition + relativeStartPosition;
3371         unsigned subrangeLength = relativeEndPosition - relativeStartPosition + 1;
3372
3373         RefPtr<Range> subrange = TextIterator::subrange(&range, subrangeOffset, subrangeLength);
3374
3375         markedRanges.append(subrange);
3376         range.ownerDocument().markers().addMarker(subrange.get(), DocumentMarker::TelephoneNumber);
3377
3378         scannerPosition += relativeEndPosition + 1;
3379     }
3380 }
3381
3382 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3383
3384 void Editor::updateEditorUINowIfScheduled()
3385 {
3386     if (!m_editorUIUpdateTimer.isActive())
3387         return;
3388     m_editorUIUpdateTimer.stop();
3389     editorUIUpdateTimerFired();
3390 }
3391
3392 void Editor::editorUIUpdateTimerFired()
3393 {
3394     VisibleSelection oldSelection = m_oldSelectionForEditorUIUpdate;
3395
3396     m_alternativeTextController->stopPendingCorrection(oldSelection);
3397     
3398     bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabled();
3399     bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && isGrammarCheckingEnabled();
3400     if (isContinuousSpellCheckingEnabled) {
3401         VisibleSelection newAdjacentWords;
3402         VisibleSelection newSelectedSentence;
3403         bool caretBrowsing = m_frame.settings().caretBrowsingEnabled();
3404         if (m_frame.selection().selection().isContentEditable() || caretBrowsing) {
3405             VisiblePosition newStart(m_frame.selection().selection().visibleStart());
3406 #if !PLATFORM(IOS)
3407             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
3408 #else
3409             // If this bug gets fixed, this PLATFORM(IOS) code could be removed:
3410             // <rdar://problem/7259611> Word boundary code on iPhone gives different results than desktop
3411             EWordSide startWordSide = LeftWordIfOnBoundary;
3412             UChar32 c = newStart.characterBefore();
3413             // FIXME: VisiblePosition::characterAfter() and characterBefore() do not emit newlines the same
3414             // way as TextIterator, so we do an isStartOfParagraph check here.
3415             if (isSpaceOrNewline(c) || c == 0xA0 || isStartOfParagraph(newStart)) {
3416                 startWordSide = RightWordIfOnBoundary;
3417             }
3418             newAdjacentWords = VisibleSelection(startOfWord(newStart, startWordSide), endOfWord(newStart, RightWordIfOnBoundary));
3419 #endif // !PLATFORM(IOS)
3420             if (isContinuousGrammarCheckingEnabled)
3421                 newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
3422         }
3423
3424         // When typing we check spelling elsewhere, so don't redo it here.
3425         // If this is a change in selection resulting from a delete operation,
3426         // oldSelection may no longer be in the document.
3427         if (m_editorUIUpdateTimerShouldCheckSpellingAndGrammar && oldSelection.isContentEditable() && oldSelection.start().deprecatedNode() && oldSelection.start().anchorNode()->inDocument()) {
3428             VisiblePosition oldStart(oldSelection.visibleStart());
3429             VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
3430             if (oldAdjacentWords != newAdjacentWords) {
3431                 if (isContinuousGrammarCheckingEnabled) {
3432                     VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
3433                     markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence);
3434                 } else
3435                     markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
3436             }
3437         }
3438
3439         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)) {
3440             if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
3441                 document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling);
3442         }
3443         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeGrammar)) {
3444             if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
3445                 document().markers().removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
3446         }
3447     }
3448
3449     // When continuous spell checking is off, existing markers disappear after the selection changes.
3450     if (!isContinuousSpellCheckingEnabled)
3451         document().markers().removeMarkers(DocumentMarker::Spelling);
3452     if (!isContinuousGrammarCheckingEnabled)
3453         document().markers().removeMarkers(DocumentMarker::Grammar);
3454
3455     if (!m_editorUIUpdateTimerWasTriggeredByDictation)
3456         m_alternativeTextController->respondToChangedSelection(oldSelection);
3457
3458     m_oldSelectionForEditorUIUpdate = m_frame.selection().selection();
3459 }
3460
3461 static Node* findFirstMarkable(Node* node)
3462 {
3463     while (node) {
3464         if (!node->renderer())
3465             return nullptr;
3466         if (node->renderer()->isTextOrLineBreak())
3467             return node;
3468         if (is<HTMLTextFormControlElement>(*node))
3469             node = downcast<HTMLTextFormControlElement>(*node).visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
3470         else if (node->firstChild())
3471             node = node->firstChild();
3472         else
3473             node = node->nextSibling();
3474     }
3475
3476     return nullptr;
3477 }
3478
3479 bool Editor::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerType, int from, int length) const
3480 {
3481     Node* node = findFirstMarkable(m_frame.selection().selection().start().deprecatedNode());
3482     if (!node)
3483         return false;
3484
3485     unsigned int startOffset = static_cast<unsigned int>(from);
3486     unsigned int endOffset = static_cast<unsigned int>(from + length);
3487     Vector<RenderedDocumentMarker*> markers = document().markers().markersFor(node);
3488     for (auto* marker : markers) {
3489         if (marker->startOffset() <= startOffset && endOffset <= marker->endOffset() && marker->type() == markerType)
3490             return true;
3491     }
3492
3493     return false;
3494 }       
3495
3496 TextCheckingTypeMask Editor::resolveTextCheckingTypeMask(TextCheckingTypeMask textCheckingOptions)
3497 {
3498     bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
3499     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
3500 #if !PLATFORM(IOS)
3501     bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
3502     bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
3503 #endif
3504
3505     TextCheckingTypeMask checkingTypes = 0;
3506     if (shouldMarkSpelling)
3507         checkingTypes |= TextCheckingTypeSpelling;
3508     if (shouldMarkGrammar)
3509         checkingTypes |= TextCheckingTypeGrammar;
3510 #if !PLATFORM(IOS)
3511     if (shouldCheckForCorrection)
3512         checkingTypes |= TextCheckingTypeCorrection;
3513     if (shouldShowCorrectionPanel)
3514         checkingTypes |= TextCheckingTypeShowCorrectionPanel;
3515
3516 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
3517     bool shouldPerformReplacement = textCheckingOptions & TextCheckingTypeReplacement;
3518     if (shouldPerformReplacement) {
3519         if (isAutomaticLinkDetectionEnabled())
3520             checkingTypes |= TextCheckingTypeLink;
3521         if (isAutomaticQuoteSubstitutionEnabled())
3522             checkingTypes |= TextCheckingTypeQuote;
3523         if (isAutomaticDashSubstitutionEnabled())
3524             checkingTypes |= TextCheckingTypeDash;
3525         if (isAutomaticTextReplacementEnabled())
3526             checkingTypes |= TextCheckingTypeReplacement;
3527         if (shouldMarkSpelling && isAutomaticSpellingCorrectionEnabled())
3528             checkingTypes |= TextCheckingTypeCorrection;
3529     }
3530 #endif
3531 #endif // !PLATFORM(IOS)
3532
3533     return checkingTypes;
3534 }
3535
3536 bool Editor::unifiedTextCheckerEnabled() const
3537 {
3538     return WebCore::unifiedTextCheckerEnabled(&m_frame);
3539 }
3540
3541 Vector<String> Editor::dictationAlternativesForMarker(const DocumentMarker* marker)
3542 {
3543     return m_alternativeTextController->dictationAlternativesForMarker(marker);
3544 }