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