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