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