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