Reviewed by Hyatt.
[WebKit-https.git] / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "Editor.h"
28
29 #include "AXObjectCache.h"
30 #include "ApplyStyleCommand.h"
31 #include "CSSComputedStyleDeclaration.h"
32 #include "CSSProperty.h"
33 #include "CSSPropertyNames.h"
34 #include "CharacterData.h"
35 #include "Clipboard.h"
36 #include "ClipboardEvent.h"
37 #include "DeleteButtonController.h"
38 #include "DeleteSelectionCommand.h"
39 #include "Document.h"
40 #include "DocumentFragment.h"
41 #include "EditCommand.h"
42 #include "Editor.h"
43 #include "EditorClient.h"
44 #include "Event.h"
45 #include "EventNames.h"
46 #include "FocusController.h"
47 #include "FontData.h"
48 #include "HTMLElement.h"
49 #include "HTMLInputElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLTextAreaElement.h"
52 #include "HitTestResult.h"
53 #include "IndentOutdentCommand.h"
54 #include "KeyboardEvent.h"
55 #include "KURL.h"
56 #include "Page.h"
57 #include "Pasteboard.h"
58 #include "Range.h"
59 #include "ReplaceSelectionCommand.h"
60 #include "SelectionController.h"
61 #include "Sound.h"
62 #include "TextIterator.h"
63 #include "TypingCommand.h"
64 #include "htmlediting.h"
65 #include "markup.h"
66
67 namespace WebCore {
68
69 using namespace EventNames;
70 using namespace HTMLNames;
71
72 // When an event handler has moved the selection outside of a text control
73 // we should use the target control's selection for this editing operation.
74 static Selection selectionForEvent(Frame* frame, Event* event)
75 {
76     Page* page = frame->page();
77     if (!page)
78         return Selection();
79     Selection selection = page->selection();
80     if (!event)
81         return selection;
82     Node* target = event->target()->toNode();
83     Node* selectionStart = selection.start().node();
84     
85     // If the target is a text control, and the current selection is outside of its shadow tree,
86     // then use the saved selection for that text control.
87     if (target && (!selectionStart || target->shadowAncestorNode() != selectionStart->shadowAncestorNode())) {
88         if (target->hasTagName(inputTag) && static_cast<HTMLInputElement*>(target)->isTextField())
89             return static_cast<HTMLInputElement*>(target)->selection();
90         if (target->hasTagName(textareaTag))
91             return static_cast<HTMLTextAreaElement*>(target)->selection();
92     }
93     return selection;
94 }
95
96 EditorClient* Editor::client() const
97 {
98     if (Page* page = m_frame->page())
99         return page->editorClient();
100     return 0;
101 }
102
103 void Editor::handleKeyPress(KeyboardEvent* event)
104 {
105     if (EditorClient* c = client())
106         if (selectionForEvent(m_frame, event).isContentEditable())
107             c->handleKeyPress(event);
108 }
109
110 bool Editor::canEdit() const
111 {
112     return m_frame->selectionController()->isContentEditable();
113 }
114
115 bool Editor::canEditRichly() const
116 {
117     return m_frame->selectionController()->isContentRichlyEditable();
118 }
119
120 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
121 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
122 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
123 // normally selectable to implement copy/paste (like divs, or a document body).
124
125 bool Editor::canDHTMLCut()
126 {
127     return !m_frame->selectionController()->isInPasswordField() && !dispatchCPPEvent(beforecutEvent, ClipboardNumb);
128 }
129
130 bool Editor::canDHTMLCopy()
131 {
132     return !m_frame->selectionController()->isInPasswordField() && !dispatchCPPEvent(beforecopyEvent, ClipboardNumb);
133 }
134
135 bool Editor::canDHTMLPaste()
136 {
137     return !dispatchCPPEvent(beforepasteEvent, ClipboardNumb);
138 }
139
140 bool Editor::canCut() const
141 {
142     return canCopy() && canDelete();
143 }
144
145 bool Editor::canCopy() const
146 {
147     SelectionController* selectionController = m_frame->selectionController();
148     return selectionController->isRange() && !selectionController->isInPasswordField();
149 }
150
151 bool Editor::canPaste() const
152 {
153     return canEdit();
154 }
155
156 bool Editor::canDelete() const
157 {
158     SelectionController* selectionController = m_frame->selectionController();
159     return selectionController->isRange() && selectionController->isContentEditable();
160 }
161
162 bool Editor::canDeleteRange(Range* range) const
163 {
164     ExceptionCode ec = 0;
165     Node* startContainer = range->startContainer(ec);
166     Node* endContainer = range->endContainer(ec);
167     if (!startContainer || !endContainer)
168         return false;
169     
170     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
171         return false;
172     
173     if (range->collapsed(ec)) {
174         VisiblePosition start(startContainer, range->startOffset(ec), DOWNSTREAM);
175         VisiblePosition previous = start.previous();
176         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
177         if (previous.isNull() || previous.deepEquivalent().node()->rootEditableElement() != startContainer->rootEditableElement())
178             return false;
179     }
180     return true;
181 }
182
183 bool Editor::smartInsertDeleteEnabled()
184 {   
185     if (client())
186         return client()->smartInsertDeleteEnabled();
187     return false;
188 }
189     
190 bool Editor::canSmartCopyOrDelete()
191 {
192     if (client())
193         return client()->smartInsertDeleteEnabled() && m_frame->selectionGranularity() == WordGranularity;
194     return false;
195 }
196
197 void Editor::deleteRange(Range* range, bool killRing, bool prepend, bool smartDeleteOK, EditorDeleteAction deletionAction, TextGranularity granularity)
198 {
199     if (killRing)
200         addToKillRing(range, prepend);
201
202     ExceptionCode ec = 0;
203
204     SelectionController* selectionController = m_frame->selectionController();
205     bool smartDelete = smartDeleteOK && canSmartCopyOrDelete();
206     switch (deletionAction) {
207         case deleteSelectionAction:
208             selectionController->setSelectedRange(range, DOWNSTREAM, true, ec);
209             if (ec)
210                 return;
211             deleteSelectionWithSmartDelete(smartDelete);
212             break;
213         case deleteKeyAction:
214             selectionController->setSelectedRange(range, DOWNSTREAM, (granularity != CharacterGranularity), ec);
215             if (ec)
216                 return;
217             if (m_frame->document()) {
218                 TypingCommand::deleteKeyPressed(m_frame->document(), smartDelete, granularity);
219                 m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
220             }
221             break;
222         case forwardDeleteKeyAction:
223             selectionController->setSelectedRange(range, DOWNSTREAM, (granularity != CharacterGranularity), ec);
224             if (ec)
225                 return;
226             if (m_frame->document()) {
227                 TypingCommand::forwardDeleteKeyPressed(m_frame->document(), smartDelete, granularity);
228                 m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
229             }
230             break;
231     }
232 }
233
234 bool Editor::deleteWithDirection(SelectionController::EDirection direction, TextGranularity granularity, bool killRing, bool isTypingAction)
235 {
236     // Delete the selection, if there is one.
237     // If not, make a selection using the passed-in direction and granularity.
238
239     if (!canEdit())
240         return false;
241
242     RefPtr<Range> range;
243     EditorDeleteAction deletionAction = deleteSelectionAction;
244
245     bool smartDeleteOK = false;
246     
247     if (m_frame->selectionController()->isRange()) {
248         range = selectedRange();
249         smartDeleteOK = true;
250         if (isTypingAction)
251             deletionAction = deleteKeyAction;
252     } else {
253         SelectionController selectionController;
254         selectionController.setSelection(m_frame->selectionController()->selection());
255         selectionController.modify(SelectionController::EXTEND, direction, granularity);
256         range = selectionController.toRange();
257         
258         switch (direction) {
259             case SelectionController::FORWARD:
260             case SelectionController::RIGHT:
261                 deletionAction = forwardDeleteKeyAction;
262                 break;
263             case SelectionController::BACKWARD:
264             case SelectionController::LEFT:
265                 deletionAction = deleteKeyAction;
266                 break;
267         }
268     }
269
270     deleteRange(range.get(), killRing, false, smartDeleteOK, deletionAction, granularity);
271
272     return true;
273 }
274
275 void Editor::deleteSelectionWithSmartDelete()
276 {
277     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
278 }
279
280 void Editor::deleteSelectionWithSmartDelete(bool smartDelete)
281 {
282     if (m_frame->selectionController()->isNone())
283         return;
284     
285     applyCommand(new DeleteSelectionCommand(m_frame->document(), smartDelete));
286 }
287
288 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard* pasteboard)
289 {
290     String text = pasteboard->plainText(m_frame);
291     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertActionPasted))
292         replaceSelectionWithText(text, false, canSmartReplaceWithPasteboard(pasteboard));
293 }
294
295 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
296 {
297     bool chosePlainText;
298     RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, selectedRange(), allowPlainText, chosePlainText);
299     if (fragment && shouldInsertFragment(fragment, selectedRange(), EditorInsertActionPasted))
300         replaceSelectionWithFragment(fragment, false, canSmartReplaceWithPasteboard(pasteboard), chosePlainText);
301 }
302
303 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard)
304 {
305     if (client())
306         return client()->smartInsertDeleteEnabled() && pasteboard->canSmartReplace();
307     return false;
308 }
309
310 bool Editor::shouldInsertFragment(PassRefPtr<DocumentFragment> fragment, PassRefPtr<Range> replacingDOMRange, EditorInsertAction givenAction)
311 {
312     if (client()) {
313         Node* child = fragment->firstChild();
314         if (fragment->lastChild() == child && child->isCharacterDataNode())
315             return client()->shouldInsertText(static_cast<CharacterData*>(child)->data(), replacingDOMRange.get(), givenAction);
316         return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
317     }
318     return false;
319 }
320
321 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
322 {
323     if (m_frame->selectionController()->isNone() || !fragment)
324         return;
325     
326     applyCommand(new ReplaceSelectionCommand(m_frame->document(), fragment, selectReplacement, smartReplace, matchStyle));
327     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
328 }
329
330 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace)
331 {
332     replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), text), selectReplacement, smartReplace, true); 
333 }
334
335 PassRefPtr<Range> Editor::selectedRange()
336 {
337     if (!m_frame)
338         return 0;
339     return m_frame->selectionController()->toRange();
340 }
341
342 bool Editor::shouldDeleteRange(Range* range) const
343 {
344     ExceptionCode ec;
345     if (!range || range->collapsed(ec))
346         return false;
347     
348     if (!canDeleteRange(range))
349         return false;
350
351     if (client())
352         return client()->shouldDeleteRange(range);
353     return false;
354 }
355
356 bool Editor::tryDHTMLCopy()
357 {   
358     if (m_frame->selectionController()->isInPasswordField())
359         return false;
360
361     // Must be done before oncopy adds types and data to the pboard,
362     // also done for security, as it erases data from the last copy/paste.
363     Pasteboard::generalPasteboard()->clear();
364
365     return !dispatchCPPEvent(copyEvent, ClipboardWritable);
366 }
367
368 bool Editor::tryDHTMLCut()
369 {
370     if (m_frame->selectionController()->isInPasswordField())
371         return false;
372
373     // Must be done before oncut adds types and data to the pboard,
374     // also done for security, as it erases data from the last copy/paste.
375     Pasteboard::generalPasteboard()->clear();
376
377     return !dispatchCPPEvent(cutEvent, ClipboardWritable);
378 }
379
380 bool Editor::tryDHTMLPaste()
381 {
382     return !dispatchCPPEvent(pasteEvent, ClipboardReadable);
383 }
384
385 void Editor::writeSelectionToPasteboard(Pasteboard* pasteboard)
386 {
387     pasteboard->writeSelection(selectedRange().get(), canSmartCopyOrDelete(), m_frame);
388 }
389
390 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
391 {
392     if (client())
393         return client()->shouldInsertText(text, range, action);
394     return false;
395 }
396
397 bool Editor::shouldShowDeleteInterface(HTMLElement* element) const
398 {
399     if (client())
400         return client()->shouldShowDeleteInterface(element);
401     return false;
402 }
403
404 void Editor::respondToChangedSelection(const Selection& oldSelection)
405 {
406     m_deleteButtonController->respondToChangedSelection(oldSelection);
407 }
408
409 void Editor::respondToChangedContents(const Selection& endingSelection)
410 {
411     if (AXObjectCache::accessibilityEnabled()) {
412         Node* node = endingSelection.start().node();
413         if (node)
414             m_frame->renderer()->document()->axObjectCache()->postNotification(node->renderer(), "AXValueChanged");
415     }
416     
417     if (client())
418         client()->respondToChangedContents();  
419     m_deleteButtonController->respondToChangedContents();
420 }
421
422 const FontData* Editor::fontForSelection(bool& hasMultipleFonts) const
423 {
424     if (hasMultipleFonts)
425         hasMultipleFonts = false;
426
427     if (!m_frame->selectionController()->isRange()) {
428         Node* nodeToRemove;
429         RenderStyle* style = m_frame->styleForSelectionStart(nodeToRemove); // sets nodeToRemove
430
431         const FontData* result = 0;
432         if (style)
433             result = style->font().primaryFont();
434         
435         if (nodeToRemove) {
436             ExceptionCode ec;
437             nodeToRemove->remove(ec);
438             ASSERT(ec == 0);
439         }
440
441         return result;
442     }
443
444     const FontData* font = 0;
445
446     RefPtr<Range> range = m_frame->selectionController()->toRange();
447     Node* startNode = range->editingStartPosition().node();
448     if (startNode) {
449         Node* pastEnd = range->pastEndNode();
450         // In the loop below, n should eventually match pastEnd and not become nil, but we've seen at least one
451         // unreproducible case where this didn't happen, so check for nil also.
452         for (Node* n = startNode; n && n != pastEnd; n = n->traverseNextNode()) {
453             RenderObject *renderer = n->renderer();
454             if (!renderer)
455                 continue;
456             // FIXME: Are there any node types that have renderers, but that we should be skipping?
457             const FontData* f = renderer->style()->font().primaryFont();
458             if (!font) {
459                 font = f;
460                 if (!hasMultipleFonts)
461                     break;
462             } else if (font != f) {
463                 hasMultipleFonts = true;
464                 break;
465             }
466         }
467     }
468
469     return font;
470 }
471
472 Frame::TriState Editor::selectionUnorderedListState() const
473 {
474     if (m_frame->selectionController()->isCaret()) {
475         Node* selectionNode = m_frame->selectionController()->selection().start().node();
476         if (enclosingNodeWithTag(selectionNode, ulTag))
477             return Frame::trueTriState;
478     } else if (m_frame->selectionController()->isRange()) {
479         Node* startNode = enclosingNodeWithTag(m_frame->selectionController()->selection().start().node(), ulTag);
480         Node* endNode = enclosingNodeWithTag(m_frame->selectionController()->selection().end().node(), ulTag);
481         if (startNode && endNode && startNode == endNode)
482             return Frame::trueTriState;
483     }
484
485     return Frame::falseTriState;
486 }
487
488 Frame::TriState Editor::selectionOrderedListState() const
489 {
490     if (m_frame->selectionController()->isCaret()) {
491         Node* selectionNode = m_frame->selectionController()->selection().start().node();
492         if (enclosingNodeWithTag(selectionNode, olTag))
493             return Frame::trueTriState;
494     } else if (m_frame->selectionController()->isRange()) {
495         Node* startNode = enclosingNodeWithTag(m_frame->selectionController()->selection().start().node(), olTag);
496         Node* endNode = enclosingNodeWithTag(m_frame->selectionController()->selection().end().node(), olTag);
497         if (startNode && endNode && startNode == endNode)
498             return Frame::trueTriState;
499     }
500
501     return Frame::falseTriState;
502 }
503
504 void Editor::removeFormattingAndStyle()
505 {
506     Document* document = m_frame->document();
507     
508     // Make a plain text string from the selection to remove formatting like tables and lists.
509     RefPtr<DocumentFragment> text = createFragmentFromText(m_frame->selectionController()->toRange().get(), m_frame->selectionController()->toString());
510     
511     // Put the fragment made from that string into a style span with the document's
512     // default style to make sure that it is unstyled regardless of where it is inserted.
513     Position pos(document->documentElement(), 0);
514     RefPtr<CSSComputedStyleDeclaration> computedStyle = pos.computedStyle();
515     RefPtr<CSSMutableStyleDeclaration> defaultStyle = computedStyle->copyInheritableProperties();
516     
517     RefPtr<Element> span = createStyleSpanElement(document);
518     span->setAttribute(styleAttr, defaultStyle->cssText());
519     
520     ExceptionCode ec;
521     
522     while (text->firstChild())
523         span->appendChild(text->firstChild(), ec);
524     
525     RefPtr<DocumentFragment> fragment = new DocumentFragment(document);
526     fragment->appendChild(span, ec);
527     
528     applyCommand(new ReplaceSelectionCommand(document, fragment, false, false, false, true, EditActionUnspecified));
529 }
530
531 void Editor::setLastEditCommand(PassRefPtr<EditCommand> lastEditCommand) 
532 {
533     m_lastEditCommand = lastEditCommand;
534 }
535
536 // Returns whether caller should continue with "the default processing", which is the same as 
537 // the event handler NOT setting the return value to false
538 bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPolicy policy)
539 {
540     Node* target = m_frame->selectionController()->start().element();
541     if (!target && m_frame->document())
542         target = m_frame->document()->body();
543     if (!target)
544         return true;
545     target = target->shadowAncestorNode();
546     
547     RefPtr<Clipboard> clipboard = newGeneralClipboard(policy);
548
549     ExceptionCode ec = 0;
550     RefPtr<Event> evt = new ClipboardEvent(eventType, true, true, clipboard.get());
551     EventTargetNodeCast(target)->dispatchEvent(evt, ec, true);
552     bool noDefaultProcessing = evt->defaultPrevented();
553
554     // invalidate clipboard here for security
555     clipboard->setAccessPolicy(ClipboardNumb);
556     
557     return !noDefaultProcessing;
558 }
559
560 void Editor::applyStyle(CSSStyleDeclaration* style, EditAction editingAction)
561 {
562     switch (m_frame->selectionController()->state()) {
563         case Selection::NONE:
564             // do nothing
565             break;
566         case Selection::CARET: {
567             m_frame->computeAndSetTypingStyle(style, editingAction);
568             break;
569         }
570         case Selection::RANGE:
571             if (m_frame->document() && style)
572                 applyCommand(new ApplyStyleCommand(m_frame->document(), style, editingAction));
573             break;
574     }
575 }
576     
577 bool Editor::shouldApplyStyle(CSSStyleDeclaration* style, Range* range)
578 {   
579     return client()->shouldApplyStyle(style, range);
580 }
581     
582 void Editor::applyParagraphStyle(CSSStyleDeclaration* style, EditAction editingAction)
583 {
584     switch (m_frame->selectionController()->state()) {
585         case Selection::NONE:
586             // do nothing
587             break;
588         case Selection::CARET:
589         case Selection::RANGE:
590             if (m_frame->document() && style)
591                 applyCommand(new ApplyStyleCommand(m_frame->document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
592             break;
593     }
594 }
595
596 void Editor::applyStyleToSelection(CSSStyleDeclaration* style, EditAction editingAction)
597 {
598     if (!style || style->length() == 0 || !canEditRichly())
599         return;
600
601     if (client() && client()->shouldApplyStyle(style, m_frame->selectionController()->toRange().get()))
602         applyStyle(style, editingAction);
603 }
604
605 void Editor::applyParagraphStyleToSelection(CSSStyleDeclaration* style, EditAction editingAction)
606 {
607     if (!style || style->length() == 0 || !canEditRichly())
608         return;
609     
610     if (client() && client()->shouldApplyStyle(style, m_frame->selectionController()->toRange().get()))
611         applyParagraphStyle(style, editingAction);
612 }
613
614 bool Editor::selectWordBeforeMenuEvent() const
615 {
616     if (client())
617         return client()->selectWordBeforeMenuEvent();
618     return false;
619 }
620
621 bool Editor::clientIsEditable() const
622 {
623     if (client())
624         return client()->isEditable();
625     return false;
626 }
627
628 bool Editor::selectionStartHasStyle(CSSStyleDeclaration* style) const
629 {
630     Node* nodeToRemove;
631     RefPtr<CSSStyleDeclaration> selectionStyle = m_frame->selectionComputedStyle(nodeToRemove);
632     if (!selectionStyle)
633         return false;
634     
635     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
636     
637     bool match = true;
638     DeprecatedValueListConstIterator<CSSProperty> end;
639     for (DeprecatedValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
640         int propertyID = (*it).id();
641         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
642             match = false;
643             break;
644         }
645     }
646     
647     if (nodeToRemove) {
648         ExceptionCode ec = 0;
649         nodeToRemove->remove(ec);
650         assert(ec == 0);
651     }
652     
653     return match;
654 }
655
656 void Editor::indent()
657 {
658     applyCommand(new IndentOutdentCommand(m_frame->document(), IndentOutdentCommand::Indent));
659 }
660
661 void Editor::outdent()
662 {
663     applyCommand(new IndentOutdentCommand(m_frame->document(), IndentOutdentCommand::Outdent));
664 }
665
666 static void dispatchEditableContentChangedEvents(const EditCommand& command)
667 {
668     Element* startRoot = command.startingRootEditableElement();
669     Element* endRoot = command.endingRootEditableElement();
670     ExceptionCode ec;
671     if (startRoot)
672         startRoot->dispatchEvent(new Event(webkitEditableContentChangedEvent, false, false), ec, true);
673     if (endRoot && endRoot != startRoot)
674         endRoot->dispatchEvent(new Event(webkitEditableContentChangedEvent, false, false), ec, true);
675 }
676
677 void Editor::appliedEditing(PassRefPtr<EditCommand> cmd)
678 {
679     dispatchEditableContentChangedEvents(*cmd);
680     
681     // FIXME: We shouldn't tell setSelection to clear the typing style or removed anchor here.
682     // If we didn't, we wouldn't have to save/restore the removedAnchor, and we wouldn't have to have
683     // the typing style stored in two places (the Frame and commands).
684     RefPtr<Node> anchor = removedAnchor();
685     
686     Selection newSelection(cmd->endingSelection());
687     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
688     // because there is work that it must do in this situation.
689     if (newSelection == m_frame->selectionController()->selection() || m_frame->shouldChangeSelection(newSelection))
690         m_frame->selectionController()->setSelection(newSelection, false);
691     
692     setRemovedAnchor(anchor);
693     
694     // Now set the typing style from the command. Clear it when done.
695     // This helps make the case work where you completely delete a piece
696     // of styled text and then type a character immediately after.
697     // That new character needs to take on the style of the just-deleted text.
698     // FIXME: Improve typing style.
699     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
700     if (cmd->typingStyle()) {
701         m_frame->setTypingStyle(cmd->typingStyle());
702         cmd->setTypingStyle(0);
703     }
704     
705     // Command will be equal to last edit command only in the case of typing
706     if (m_lastEditCommand.get() == cmd)
707         ASSERT(cmd->isTypingCommand());
708     else {
709         // Only register a new undo command if the command passed in is
710         // different from the last command
711         m_lastEditCommand = cmd;
712         if (client())
713             client()->registerCommandForUndo(m_lastEditCommand);
714     }
715     respondToChangedContents(newSelection);    
716 }
717
718 void Editor::unappliedEditing(PassRefPtr<EditCommand> cmd)
719 {
720     dispatchEditableContentChangedEvents(*cmd);
721     
722     Selection newSelection(cmd->startingSelection());
723     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
724     // because there is work that it must do in this situation.
725     if (newSelection == m_frame->selectionController()->selection() || m_frame->shouldChangeSelection(newSelection))
726         m_frame->selectionController()->setSelection(newSelection, true);
727     
728     m_lastEditCommand = 0;
729     if (client())
730         client()->registerCommandForRedo(cmd);
731     respondToChangedContents(newSelection);    
732 }
733
734 void Editor::reappliedEditing(PassRefPtr<EditCommand> cmd)
735 {
736     dispatchEditableContentChangedEvents(*cmd);
737     
738     Selection newSelection(cmd->endingSelection());
739     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
740     // because there is work that it must do in this situation.
741     if (newSelection == m_frame->selectionController()->selection() || m_frame->shouldChangeSelection(newSelection))
742         m_frame->selectionController()->setSelection(newSelection, true);
743     
744     m_lastEditCommand = 0;
745     if (client())
746         client()->registerCommandForUndo(cmd);
747     respondToChangedContents(newSelection);    
748 }
749
750 // Execute command functions
751
752 static bool execCopy(Frame* frame)
753 {
754     frame->editor()->copy();
755     return true;
756 }
757
758 static bool execCut(Frame* frame)
759 {
760     frame->editor()->cut();
761     return true;
762 }
763
764 static bool execDelete(Frame* frame)
765 {
766     frame->editor()->performDelete();
767     return true;
768 }
769
770 static bool execBackwardDelete(Frame* frame)
771 {
772     frame->editor()->deleteWithDirection(SelectionController::BACKWARD, CharacterGranularity, false, true);
773     return true;
774 }
775
776 static bool execForwardDelete(Frame* frame)
777 {
778     frame->editor()->deleteWithDirection(SelectionController::FORWARD, CharacterGranularity, false, true);
779     return true;
780 }
781
782 static bool execMoveBackward(Frame* frame)
783 {
784     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, CharacterGranularity, true);
785     return true;
786 }
787
788 static bool execMoveBackwardAndModifySelection(Frame* frame)
789 {
790     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, CharacterGranularity, true);
791     return true;
792 }
793
794 static bool execMoveUpByPageAndModifyCaret(Frame* frame)
795 {
796     RenderObject* renderer = frame->document()->focusedNode()->renderer();
797     if (renderer->style()->overflowY() == OSCROLL
798         || renderer->style()->overflowY() == OAUTO
799         || renderer->isTextArea()) {
800         int height = -(frame->document()->focusedNode()->renderer()->clientHeight()-PAGE_KEEP);
801         bool handledScroll = renderer->scroll(ScrollUp, ScrollByPage);
802         bool handledCaretMove = frame->selectionController()->modify(SelectionController::MOVE, height);
803         return handledScroll || handledCaretMove;
804     }
805     return false;
806 }
807
808 static bool execMoveDown(Frame* frame)
809 {
810     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true);
811     return true;
812 }
813
814 static bool execMoveDownAndModifySelection(Frame* frame)
815 {
816     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, LineGranularity, true);
817     return true;
818 }
819
820 static bool execMoveForward(Frame* frame)
821 {
822     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, CharacterGranularity, true);
823     return true;
824 }
825
826 static bool execMoveForwardAndModifySelection(Frame* frame)
827 {
828     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, CharacterGranularity, true);
829     return true;
830 }
831
832 static bool execMoveDownByPageAndModifyCaret(Frame* frame)
833 {
834     RenderObject* renderer = frame->document()->focusedNode()->renderer();
835     if (renderer->style()->overflowY() == OSCROLL
836         || renderer->style()->overflowY() == OAUTO
837         || renderer->isTextArea()) {
838         int height = frame->document()->focusedNode()->renderer()->clientHeight()-PAGE_KEEP;
839         bool handledScroll = renderer->scroll(ScrollDown, ScrollByPage);
840         bool handledCaretMove = frame->selectionController()->modify(SelectionController::MOVE, height);
841         return handledScroll || handledCaretMove;
842     }
843     return false;
844 }
845
846 static bool execMoveLeft(Frame* frame)
847 {
848     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::LEFT, CharacterGranularity, true);
849     return true;
850 }
851
852 static bool execMoveLeftAndModifySelection(Frame* frame)
853 {
854     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::LEFT, CharacterGranularity, true);
855     return true;
856 }
857
858 static bool execMoveRight(Frame* frame)
859 {
860     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::RIGHT, CharacterGranularity, true);
861     return true;
862 }
863
864 static bool execMoveRightAndModifySelection(Frame* frame)
865 {
866     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::RIGHT, CharacterGranularity, true);
867     return true;
868 }
869
870 static bool execMoveToBeginningOfDocument(Frame* frame)
871 {
872     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, DocumentBoundary, true);
873     return true;
874 }
875
876 static bool execMoveToBeginningOfDocumentAndModifySelection(Frame* frame)
877 {
878     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, DocumentBoundary, true);
879     return true;
880 }
881
882 static bool execMoveToBeginningOfSentence(Frame* frame)
883 {
884     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, SentenceBoundary, true);
885     return true;
886 }
887
888 static bool execMoveToBeginningOfSentenceAndModifySelection(Frame* frame)
889 {
890     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, SentenceBoundary, true);
891     return true;
892 }
893
894 static bool execMoveToBeginningOfLine(Frame* frame)
895 {
896     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, LineBoundary, true);
897     return true;
898 }
899
900 static bool execMoveToBeginningOfLineAndModifySelection(Frame* frame)
901 {
902     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, LineBoundary, true);
903     return true;
904 }
905
906 static bool execMoveToBeginningOfParagraph(Frame* frame)
907 {
908     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, ParagraphBoundary, true);
909     return true;
910 }
911
912 static bool execMoveToBeginningOfParagraphAndModifySelection(Frame* frame)
913 {
914     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, ParagraphBoundary, true);
915     return true;
916 }
917
918 static bool execMoveToEndOfDocument(Frame* frame)
919 {
920     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, DocumentBoundary, true);
921     return true;
922 }
923
924 static bool execMoveToEndOfDocumentAndModifySelection(Frame* frame)
925 {
926     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, DocumentBoundary, true);
927     return true;
928 }
929
930 static bool execMoveToEndOfSentence(Frame* frame)
931 {
932     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, SentenceBoundary, true);
933     return true;
934 }
935
936 static bool execMoveToEndOfSentenceAndModifySelection(Frame* frame)
937 {
938     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, SentenceBoundary, true);
939     return true;
940 }
941
942 static bool execMoveToEndOfLine(Frame* frame)
943 {
944     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, LineBoundary, true);
945     return true;
946 }
947
948 static bool execMoveToEndOfLineAndModifySelection(Frame* frame)
949 {
950     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, LineBoundary, true);
951     return true;
952 }
953
954 static bool execMoveToEndOfParagraph(Frame* frame)
955 {
956     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, ParagraphBoundary, true);
957     return true;
958 }
959
960 static bool execMoveToEndOfParagraphAndModifySelection(Frame* frame)
961 {
962     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, ParagraphBoundary, true);
963     return true;
964 }
965
966 static bool execMoveParagraphBackwardAndModifySelection(Frame* frame)
967 {
968     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, ParagraphGranularity, true);
969     return true;
970 }
971
972 static bool execMoveParagraphForwardAndModifySelection(Frame* frame)
973 {
974     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, ParagraphGranularity, true);
975     return true;
976 }
977
978 static bool execMoveUp(Frame* frame)
979 {
980     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true);
981     return true;
982 }
983
984 static bool execMoveUpAndModifySelection(Frame* frame)
985 {
986     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, LineGranularity, true);
987     return true;
988 }
989
990 static bool execMoveWordBackward(Frame* frame)
991 {
992     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, WordGranularity, true);
993     return true;
994 }
995
996 static bool execMoveWordBackwardAndModifySelection(Frame* frame)
997 {
998     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, WordGranularity, true);
999     return true;
1000 }
1001
1002 static bool execMoveWordForward(Frame* frame)
1003 {
1004     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, WordGranularity, true);
1005     return true;
1006 }
1007
1008 static bool execMoveWordForwardAndModifySelection(Frame* frame)
1009 {
1010     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, WordGranularity, true);
1011     return true;
1012 }
1013
1014 static bool execMoveWordLeft(Frame* frame)
1015 {
1016     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::LEFT, WordGranularity, true);
1017     return true;
1018 }
1019
1020 static bool execMoveWordLeftAndModifySelection(Frame* frame)
1021 {
1022     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::LEFT, WordGranularity, true);
1023     return true;
1024 }
1025
1026 static bool execMoveWordRight(Frame* frame)
1027 {
1028     frame->selectionController()->modify(SelectionController::MOVE, SelectionController::RIGHT, WordGranularity, true);
1029     return true;
1030 }
1031
1032 static bool execMoveWordRightAndModifySelection(Frame* frame)
1033 {
1034     frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::RIGHT, WordGranularity, true);
1035     return true;
1036 }
1037
1038 static bool execPaste(Frame* frame)
1039 {
1040     frame->editor()->paste();
1041     return true;
1042 }
1043
1044 static bool execSelectAll(Frame* frame)
1045 {
1046     frame->selectionController()->selectAll();
1047     return true;
1048 }
1049
1050 static bool execToggleBold(Frame* frame)
1051 {
1052     ExceptionCode ec;
1053     
1054     RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
1055     style->setProperty(CSS_PROP_FONT_WEIGHT, "bold", false, ec);
1056     if (frame->editor()->selectionStartHasStyle(style.get()))
1057         style->setProperty(CSS_PROP_FONT_WEIGHT, "normal", false, ec);
1058     frame->editor()->applyStyleToSelection(style.get(), EditActionSetFont);
1059     return true;
1060 }
1061
1062 static bool execToggleItalic(Frame* frame)
1063 {
1064     ExceptionCode ec;
1065     
1066     RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
1067     style->setProperty(CSS_PROP_FONT_STYLE, "italic", false, ec);
1068     if (frame->editor()->selectionStartHasStyle(style.get()))
1069         style->setProperty(CSS_PROP_FONT_STYLE, "normal", false, ec);
1070     frame->editor()->applyStyleToSelection(style.get(), EditActionSetFont);
1071     return true;
1072 }
1073
1074 static bool execRedo(Frame* frame)
1075 {
1076     frame->editor()->redo();
1077     return true;
1078 }
1079
1080 static bool execUndo(Frame* frame)
1081 {
1082     frame->editor()->undo();
1083     return true;
1084 }
1085
1086 // Enabled functions
1087
1088 static bool enabled(Frame*)
1089 {
1090     return true;
1091 }
1092
1093 static bool canPaste(Frame* frame)
1094 {
1095     return frame->editor()->canPaste();
1096 }
1097
1098 static bool hasEditableSelection(Frame* frame)
1099 {
1100     return frame->selectionController()->isContentEditable();
1101 }
1102
1103 static bool hasEditableRangeSelection(Frame* frame)
1104 {
1105     return frame->selectionController()->isRange() && frame->selectionController()->isContentEditable();
1106 }
1107
1108 static bool hasRangeSelection(Frame* frame)
1109 {
1110     return frame->selectionController()->isRange();
1111 }
1112
1113 static bool hasRichlyEditableSelection(Frame* frame)
1114 {
1115     return frame->selectionController()->isCaretOrRange() && frame->selectionController()->isContentRichlyEditable();
1116 }
1117
1118 static bool canRedo(Frame* frame)
1119 {
1120     return frame->editor()->canRedo();
1121 }
1122
1123 static bool canUndo(Frame* frame)
1124 {
1125     return frame->editor()->canUndo();
1126 }
1127
1128 struct Command {
1129     bool (*enabled)(Frame* frame);
1130     bool (*exec)(Frame* frame);
1131 };
1132
1133 typedef HashMap<RefPtr<AtomicStringImpl>, const Command*> CommandMap;
1134
1135 static CommandMap* createCommandMap()
1136 {
1137     struct CommandEntry { const char* name; Command command; };
1138     
1139     static const CommandEntry commands[] = {
1140         { "BackwardDelete", { hasEditableSelection, execBackwardDelete } },
1141         { "Copy", { hasRangeSelection, execCopy } },
1142         { "Cut", { hasEditableRangeSelection, execCut } },
1143         { "Delete", { hasEditableSelection, execDelete } },
1144         { "ForwardDelete", { hasEditableSelection, execForwardDelete } },
1145         { "MoveBackward", { hasEditableSelection, execMoveBackward } },
1146         { "MoveBackwardAndModifySelection", { hasEditableSelection, execMoveBackwardAndModifySelection } },
1147         { "MoveUpByPageAndModifyCaret", { hasEditableSelection, execMoveUpByPageAndModifyCaret } },
1148         { "MoveDown", { hasEditableSelection, execMoveDown } },
1149         { "MoveDownAndModifySelection", { hasEditableSelection, execMoveDownAndModifySelection } },
1150         { "MoveForward", { hasEditableSelection, execMoveForward } },
1151         { "MoveForwardAndModifySelection", { hasEditableSelection, execMoveForwardAndModifySelection } },
1152         { "MoveDownByPageAndModifyCaret", { hasEditableSelection, execMoveDownByPageAndModifyCaret } },
1153         { "MoveLeft", { hasEditableSelection, execMoveLeft } },
1154         { "MoveLeftAndModifySelection", { hasEditableSelection, execMoveLeftAndModifySelection } },
1155         { "MoveRight", { hasEditableSelection, execMoveRight } },
1156         { "MoveRightAndModifySelection", { hasEditableSelection, execMoveRightAndModifySelection } },
1157         { "MoveToBeginningOfDocument", { hasEditableSelection, execMoveToBeginningOfDocument } },
1158         { "MoveToBeginningOfDocumentAndModifySelection", { hasEditableSelection, execMoveToBeginningOfDocumentAndModifySelection } },
1159         { "MoveToBeginningOfSentence", { hasEditableSelection, execMoveToBeginningOfSentence } },
1160         { "MoveToBeginningOfSentenceAndModifySelection", { hasEditableSelection, execMoveToBeginningOfSentenceAndModifySelection } },
1161         { "MoveToBeginningOfLine", { hasEditableSelection, execMoveToBeginningOfLine } },
1162         { "MoveToBeginningOfLineAndModifySelection", { hasEditableSelection, execMoveToBeginningOfLineAndModifySelection } },
1163         { "MoveToBeginningOfParagraph", { hasEditableSelection, execMoveToBeginningOfParagraph } },
1164         { "MoveToBeginningOfParagraphAndModifySelection", { hasEditableSelection, execMoveToBeginningOfParagraphAndModifySelection } },
1165         { "MoveToEndOfDocument", { hasEditableSelection, execMoveToEndOfDocument } },
1166         { "MoveToEndOfDocumentAndModifySelection", { hasEditableSelection, execMoveToEndOfDocumentAndModifySelection } },
1167         { "MoveToEndOfSentence", { hasEditableSelection, execMoveToEndOfSentence } },
1168         { "MoveToEndOfSentenceAndModifySelection", { hasEditableSelection, execMoveToEndOfSentenceAndModifySelection } },
1169         { "MoveToEndOfLine", { hasEditableSelection, execMoveToEndOfLine } },
1170         { "MoveToEndOfLineAndModifySelection", { hasEditableSelection, execMoveToEndOfLineAndModifySelection } },
1171         { "MoveToEndOfParagraph", { hasEditableSelection, execMoveToEndOfParagraph } },
1172         { "MoveToEndOfParagraphAndModifySelection", { hasEditableSelection, execMoveToEndOfParagraphAndModifySelection } },
1173         { "MoveParagraphBackwardAndModifySelection", { hasEditableSelection, execMoveParagraphBackwardAndModifySelection } },
1174         { "MoveParagraphForwardAndModifySelection", { hasEditableSelection, execMoveParagraphForwardAndModifySelection } },
1175         { "MoveUp", { hasEditableSelection, execMoveUp } },
1176         { "MoveUpAndModifySelection", { hasEditableSelection, execMoveUpAndModifySelection } },
1177         { "MoveWordBackward", { hasEditableSelection, execMoveWordBackward } },
1178         { "MoveWordBackwardAndModifySelection", { hasEditableSelection, execMoveWordBackwardAndModifySelection } },
1179         { "MoveWordForward", { hasEditableSelection, execMoveWordForward } },
1180         { "MoveWordForwardAndModifySelection", { hasEditableSelection, execMoveWordForwardAndModifySelection } },
1181         { "MoveWordLeft", { hasEditableSelection, execMoveWordLeft } },
1182         { "MoveWordLeftAndModifySelection", { hasEditableSelection, execMoveWordLeftAndModifySelection } },
1183         { "MoveWordRight", { hasEditableSelection, execMoveWordRight } },
1184         { "MoveWordRightAndModifySelection", { hasEditableSelection, execMoveWordRightAndModifySelection } },
1185         { "Paste", { canPaste, execPaste } },
1186         { "Redo", { canRedo, execRedo } },
1187         { "SelectAll", { enabled, execSelectAll } },
1188         { "ToggleBold", { hasRichlyEditableSelection, execToggleBold } },
1189         { "ToggleItalic", { hasRichlyEditableSelection, execToggleItalic } },
1190         { "Undo", { canUndo, execUndo } }
1191     };
1192
1193     CommandMap* commandMap = new CommandMap;
1194
1195     const unsigned numCommands = sizeof(commands) / sizeof(commands[0]);
1196     for (unsigned i = 0; i < numCommands; i++)
1197         commandMap->set(AtomicString(commands[i].name).impl(), &commands[i].command);
1198
1199     return commandMap;
1200 }
1201
1202 // =============================================================================
1203 //
1204 // public editing commands
1205 //
1206 // =============================================================================
1207
1208 Editor::Editor(Frame* frame)
1209     : m_frame(frame)
1210     , m_deleteButtonController(new DeleteButtonController(frame))
1211     , m_ignoreMarkedTextSelectionChange(false)
1212
1213 }
1214
1215 Editor::~Editor()
1216 {
1217 }
1218
1219 bool Editor::execCommand(const AtomicString& command)
1220 {
1221     static CommandMap* commandMap;
1222     if (!commandMap)
1223         commandMap = createCommandMap();
1224     
1225     const Command* c = commandMap->get(command.impl());
1226     ASSERT(c);
1227     
1228     bool handled = false;
1229     
1230     if (c->enabled(m_frame)) {
1231         m_frame->document()->updateLayoutIgnorePendingStylesheets();
1232         handled = c->exec(m_frame);
1233     }
1234     
1235     return handled;
1236 }
1237
1238 bool Editor::insertText(const String& text, bool selectInsertedText, Event* triggeringEvent)
1239 {
1240     if (text.isEmpty())
1241         return false;
1242
1243     RefPtr<Range> range = m_frame->markedTextRange();
1244     if (!range) {
1245         Selection selection = selectionForEvent(m_frame, triggeringEvent);
1246         if (!selection.isContentEditable())
1247             return false;
1248         range = selection.toRange();
1249     }
1250
1251     if (!shouldInsertText(text, range.get(), EditorInsertActionTyped)) {
1252         discardMarkedText();
1253         return true;
1254     }
1255
1256     setIgnoreMarkedTextSelectionChange(true);
1257
1258     // If we had marked text, replace that instead of the selection/caret.
1259     selectMarkedText();
1260
1261     // Get the selection to use for the event that triggered this insertText.
1262     // If the event handler changed the selection, we may want to use a different selection
1263     // that is contained in the event target.
1264     Selection selection = selectionForEvent(m_frame, triggeringEvent);
1265     if (selection.isContentEditable()) {
1266         if (Node* selectionStart = selection.start().node()) {
1267             RefPtr<Document> document = selectionStart->document();
1268             
1269             // Insert the text
1270             TypingCommand::insertText(document.get(), text, selection, selectInsertedText);
1271
1272             // Reveal the current selection 
1273             if (Frame* editedFrame = document->frame())
1274                 if (Page* page = editedFrame->page())
1275                     page->focusController()->focusedOrMainFrame()->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1276         }
1277     }
1278
1279     setIgnoreMarkedTextSelectionChange(false);
1280
1281     // Inserting unmarks any marked text.
1282     unmarkText();
1283
1284     return true;
1285 }
1286
1287 bool Editor::insertLineBreak()
1288 {
1289     if (!canEdit())
1290         return false;
1291
1292     if (!shouldInsertText("\n", m_frame->selectionController()->toRange().get(), EditorInsertActionTyped))
1293         return true;
1294
1295     TypingCommand::insertLineBreak(m_frame->document());
1296     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1297     return true;
1298 }
1299
1300 bool Editor::insertParagraphSeparator()
1301 {
1302     if (!canEdit())
1303         return false;
1304
1305     if (!canEditRichly())
1306         return insertLineBreak();
1307
1308     if (!shouldInsertText("\n", m_frame->selectionController()->toRange().get(), EditorInsertActionTyped))
1309         return true;
1310
1311     TypingCommand::insertParagraphSeparator(m_frame->document());
1312     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1313     return true;
1314 }
1315
1316 void Editor::cut()
1317 {
1318     if (tryDHTMLCut())
1319         return; // DHTML did the whole operation
1320     if (!canCut()) {
1321         systemBeep();
1322         return;
1323     }
1324     RefPtr<Range> selection = selectedRange();
1325     if (shouldDeleteRange(selection.get())) {
1326         Pasteboard::generalPasteboard()->writeSelection(selection.get(), canSmartCopyOrDelete(), m_frame);
1327         didWriteSelectionToPasteboard();
1328         deleteSelectionWithSmartDelete();
1329     }
1330 }
1331
1332 void Editor::copy()
1333 {
1334     if (tryDHTMLCopy())
1335         return; // DHTML did the whole operation
1336     if (!canCopy()) {
1337         systemBeep();
1338         return;
1339     }
1340     Pasteboard::generalPasteboard()->writeSelection(selectedRange().get(), canSmartCopyOrDelete(), m_frame);
1341     didWriteSelectionToPasteboard();
1342 }
1343
1344 void Editor::paste()
1345 {
1346     if (tryDHTMLPaste())
1347         return;     // DHTML did the whole operation
1348     if (!canPaste())
1349         return;
1350     if (canEditRichly()) // or should we call m_frame->selectionController()->isContentRichlyEditable()
1351         pasteWithPasteboard(Pasteboard::generalPasteboard(), true);
1352     else
1353         pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
1354 }
1355
1356 void Editor::performDelete()
1357 {
1358     if (!canDelete()) {
1359         systemBeep();
1360         return;
1361     }
1362     deleteRange(selectedRange().get(), true, false, true, deleteSelectionAction, CharacterGranularity);
1363 }
1364
1365 void Editor::copyURL(const KURL& url, const String& title)
1366 {
1367     Pasteboard::generalPasteboard()->writeURL(url, title, m_frame);
1368 }
1369
1370 bool Editor::isContinuousSpellCheckingEnabled()
1371 {
1372     if (client())
1373         return client()->isContinuousSpellCheckingEnabled();
1374     return false;
1375 }
1376
1377 void Editor::toggleContinuousSpellChecking()
1378 {
1379     if (client())
1380         client()->toggleContinuousSpellChecking();
1381 }
1382
1383 bool Editor::isGrammarCheckingEnabled()
1384 {
1385     if (client())
1386         return client()->isGrammarCheckingEnabled();
1387     return false;
1388 }
1389
1390 void Editor::toggleGrammarChecking()
1391 {
1392     if (client())
1393         client()->toggleGrammarChecking();
1394 }
1395
1396 int Editor::spellCheckerDocumentTag()
1397 {
1398     if (client())
1399         return client()->spellCheckerDocumentTag();
1400     return 0;
1401 }
1402
1403 bool Editor::shouldEndEditing(Range* range)
1404 {
1405     if (client())
1406         return client()->shouldEndEditing(range);
1407     return false;
1408 }
1409
1410 bool Editor::shouldBeginEditing(Range* range)
1411 {
1412     if (client())
1413         return client()->shouldBeginEditing(range);
1414     return false;
1415 }
1416
1417 void Editor::clearUndoRedoOperations()
1418 {
1419     if (client())
1420         client()->clearUndoRedoOperations();
1421 }
1422
1423 bool Editor::canUndo()
1424 {
1425     if (client())
1426         return client()->canUndo();
1427     return false;
1428 }
1429
1430 void Editor::undo()
1431 {
1432     if (client())
1433         client()->undo();
1434 }
1435
1436 bool Editor::canRedo()
1437 {
1438     if (client())
1439         return client()->canRedo();
1440     return false;
1441 }
1442
1443 void Editor::redo()
1444 {
1445     if (client())
1446         client()->redo();
1447 }
1448
1449 void Editor::didBeginEditing()
1450 {
1451     if (client())
1452         client()->didBeginEditing();
1453 }
1454
1455 void Editor::didEndEditing()
1456 {
1457     if (client())
1458         client()->didEndEditing();
1459 }
1460
1461 void Editor::didWriteSelectionToPasteboard()
1462 {
1463     if (client())
1464         client()->didWriteSelectionToPasteboard();
1465 }
1466
1467 void Editor::toggleBold()
1468 {
1469     execToggleBold(frame());
1470 }
1471
1472 void Editor::toggleUnderline()
1473 {
1474     ExceptionCode ec = 0;
1475
1476     RefPtr<CSSStyleDeclaration> style = frame()->document()->createCSSStyleDeclaration();
1477     style->setProperty(CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT, "underline", false, ec);
1478     if (selectionStartHasStyle(style.get()))
1479         style->setProperty(CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT, "none", false, ec);
1480     applyStyleToSelection(style.get(), EditActionUnderline);
1481 }
1482
1483 void Editor::setBaseWritingDirection(String direction)
1484 {
1485     ExceptionCode ec = 0;
1486
1487     RefPtr<CSSStyleDeclaration> style = frame()->document()->createCSSStyleDeclaration();
1488     style->setProperty(CSS_PROP_DIRECTION, direction, false, ec);
1489     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
1490 }
1491
1492 void Editor::selectMarkedText()
1493 {
1494     Range* range = m_frame->markedTextRange();
1495     if (!range)
1496         return;
1497     ExceptionCode ec = 0;
1498     m_frame->selectionController()->setSelectedRange(m_frame->markedTextRange(), DOWNSTREAM, false, ec);
1499 }
1500
1501 void Editor::discardMarkedText()
1502 {
1503     if (!m_frame->markedTextRange())
1504         return;
1505
1506     setIgnoreMarkedTextSelectionChange(true);
1507
1508     selectMarkedText();
1509     unmarkText();
1510 #if PLATFORM(MAC)
1511     if (EditorClient* c = client())
1512         c->markedTextAbandoned(m_frame);
1513 #endif
1514     deleteSelectionWithSmartDelete(false);
1515
1516     setIgnoreMarkedTextSelectionChange(false);
1517 }
1518
1519 #if !PLATFORM(MAC)
1520 void Editor::unmarkText()
1521 {
1522 }
1523 #endif
1524
1525 } // namespace WebCore