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