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