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