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