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