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