Reviewed by Anders.
[WebKit-https.git] / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "Editor.h"
28
29 #include "DeleteButtonController.h"
30 #include "EditorClient.h"
31 #include "Frame.h"
32 #include "HTMLElement.h"
33 #include "Range.h"
34 #include "Sound.h"
35
36 namespace WebCore {
37
38 // implement as platform-specific
39 static Pasteboard generalPasteboard()
40 {
41     return 0;
42 }
43
44 bool Editor::canCopy()
45 {
46     return false;
47 }
48
49 bool Editor::canCut()
50 {
51     return false;
52 }
53
54 bool Editor::canDelete()
55 {
56     return false;
57 }
58
59 bool Editor::canDeleteRange(Range* range)
60 {
61     ExceptionCode ec = 0;
62     Node* startContainer = range->startContainer(ec);
63     Node* endContainer = range->endContainer(ec);
64     if (!startContainer || !endContainer)
65         return false;
66     
67     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
68         return false;
69     
70     if (range->collapsed(ec)) {
71         VisiblePosition start(startContainer, range->startOffset(ec), DOWNSTREAM);
72         VisiblePosition previous = start.previous();
73         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
74         if (previous.isNull() || previous.deepEquivalent().node()->rootEditableElement() != startContainer->rootEditableElement())
75             return false;
76     }
77     return true;
78 }
79
80 bool Editor::canPaste()
81 {
82     return false;
83 }
84
85 bool Editor::canSmartCopyOrDelete()
86 {
87     return false;
88 }
89
90 void Editor::deleteSelection()
91 {
92 }
93
94 void Editor::deleteSelectionWithSmartDelete(bool enabled)
95 {
96 }
97
98 bool Editor::isSelectionRichlyEditable()
99 {
100     return false;
101 }
102
103 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard pasteboard)
104 {
105 }
106
107 void Editor::pasteWithPasteboard(Pasteboard pasteboard, bool allowPlainText)
108 {
109 }
110
111 Range* Editor::selectedRange()
112 {
113     return 0;
114 }
115
116 bool Editor::shouldDeleteRange(Range* range)
117 {
118     ExceptionCode ec;
119     if (!range || range->collapsed(ec))
120         return false;
121     
122     if (!canDeleteRange(range))
123         return false;
124
125     return m_client->shouldDeleteRange(range);
126  }
127
128 bool Editor::tryDHTMLCopy()
129 {
130     bool handled = false;
131     return handled;
132 }
133
134 bool Editor::tryDHTMLCut()
135 {
136     bool handled = false;
137     return handled;
138 }
139
140 bool Editor::tryDHTMLPaste()
141 {
142     bool handled = false;
143     return handled;
144 }
145
146 void Editor::writeSelectionToPasteboard(Pasteboard pasteboard)
147 {
148 }
149
150 bool Editor::shouldShowDeleteInterface(HTMLElement* element)
151 {
152     return m_client->shouldShowDeleteInterface(element);
153 }
154
155 void Editor::respondToChangedSelection(const Selection& oldSelection)
156 {
157     m_deleteButtonController->respondToChangedSelection(oldSelection);
158 }
159
160 void Editor::respondToChangedContents()
161 {
162     m_deleteButtonController->respondToChangedContents();
163 }
164
165 // =============================================================================
166 //
167 // public editing commands
168 //
169 // =============================================================================
170
171 Editor::Editor(Frame* frame, PassRefPtr<EditorClient> client)
172     : m_frame(frame)
173     , m_client(client)
174     , m_deleteButtonController(new DeleteButtonController(frame))
175
176 }
177
178 Editor::~Editor()
179 {
180 }
181
182 void Editor::cut()
183 {
184     if (tryDHTMLCut())
185         return; // DHTML did the whole operation
186     if (!canCut()) {
187         systemBeep();
188         return;
189     }
190     
191     if (shouldDeleteRange(selectedRange())) {
192         writeSelectionToPasteboard(generalPasteboard());
193         deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
194     }
195 }
196
197 void Editor::copy()
198 {
199     if (tryDHTMLCopy())
200         return; // DHTML did the whole operation
201     if (!canCopy()) {
202         systemBeep();
203         return;
204     }
205     writeSelectionToPasteboard(generalPasteboard());
206 }
207
208 void Editor::paste()
209 {
210     if (tryDHTMLPaste())
211         return;     // DHTML did the whole operation
212     if (!canPaste())
213         return;
214     if (isSelectionRichlyEditable())
215         pasteWithPasteboard(generalPasteboard(), true);
216     else
217         pasteAsPlainTextWithPasteboard(generalPasteboard());
218 }
219
220 void Editor::performDelete()
221 {
222     if (!canDelete()) {
223         systemBeep();
224         return;
225     }
226     deleteSelection();
227 }
228
229 } // namespace WebCore