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