LayoutTests:
[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 "htmlediting.h"
32 #include "HTMLElement.h"
33 #include "HTMLNames.h"
34 #include "Range.h"
35 #include "SelectionController.h"
36 #include "Sound.h"
37
38 namespace WebCore {
39
40 using namespace HTMLNames;
41
42 // implement as platform-specific
43 static Pasteboard generalPasteboard()
44 {
45     return 0;
46 }
47
48 bool Editor::canCopy()
49 {
50     return false;
51 }
52
53 bool Editor::canCut()
54 {
55     return false;
56 }
57
58 bool Editor::canDelete()
59 {
60     return false;
61 }
62
63 bool Editor::canDeleteRange(Range* range)
64 {
65     ExceptionCode ec = 0;
66     Node* startContainer = range->startContainer(ec);
67     Node* endContainer = range->endContainer(ec);
68     if (!startContainer || !endContainer)
69         return false;
70     
71     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
72         return false;
73     
74     if (range->collapsed(ec)) {
75         VisiblePosition start(startContainer, range->startOffset(ec), DOWNSTREAM);
76         VisiblePosition previous = start.previous();
77         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
78         if (previous.isNull() || previous.deepEquivalent().node()->rootEditableElement() != startContainer->rootEditableElement())
79             return false;
80     }
81     return true;
82 }
83
84 bool Editor::canPaste()
85 {
86     return false;
87 }
88
89 bool Editor::canSmartCopyOrDelete()
90 {
91     return false;
92 }
93
94 void Editor::deleteSelection()
95 {
96 }
97
98 void Editor::deleteSelectionWithSmartDelete(bool enabled)
99 {
100 }
101
102 bool Editor::isSelectionRichlyEditable()
103 {
104     return false;
105 }
106
107 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard pasteboard)
108 {
109 }
110
111 void Editor::pasteWithPasteboard(Pasteboard pasteboard, bool allowPlainText)
112 {
113 }
114
115 Range* Editor::selectedRange()
116 {
117     return 0;
118 }
119
120 bool Editor::shouldDeleteRange(Range* range)
121 {
122     ExceptionCode ec;
123     if (!range || range->collapsed(ec))
124         return false;
125     
126     if (!canDeleteRange(range))
127         return false;
128
129     return m_client->shouldDeleteRange(range);
130  }
131
132 bool Editor::tryDHTMLCopy()
133 {
134     bool handled = false;
135     return handled;
136 }
137
138 bool Editor::tryDHTMLCut()
139 {
140     bool handled = false;
141     return handled;
142 }
143
144 bool Editor::tryDHTMLPaste()
145 {
146     bool handled = false;
147     return handled;
148 }
149
150 void Editor::writeSelectionToPasteboard(Pasteboard pasteboard)
151 {
152 }
153
154 bool Editor::shouldShowDeleteInterface(HTMLElement* element)
155 {
156     return m_client->shouldShowDeleteInterface(element);
157 }
158
159 void Editor::respondToChangedSelection(const Selection& oldSelection)
160 {
161     m_deleteButtonController->respondToChangedSelection(oldSelection);
162 }
163
164 void Editor::respondToChangedContents()
165 {
166     m_deleteButtonController->respondToChangedContents();
167 }
168
169 Frame::TriState Editor::selectionUnorderedListState() const
170 {
171     if (m_frame->selectionController()->isCaret()) {
172         Node* selectionNode = m_frame->selectionController()->selection().start().node();
173         if (enclosingNodeWithTag(selectionNode, ulTag))
174             return Frame::trueTriState;
175     } else if (m_frame->selectionController()->isRange()) {
176         Node* startNode = enclosingNodeWithTag(m_frame->selectionController()->selection().start().node(), ulTag);
177         Node* endNode = enclosingNodeWithTag(m_frame->selectionController()->selection().end().node(), ulTag);
178         if (startNode && endNode && startNode == endNode)
179             return Frame::trueTriState;
180     }
181
182     return Frame::falseTriState;
183 }
184
185 Frame::TriState Editor::selectionOrderedListState() const
186 {
187     if (m_frame->selectionController()->isCaret()) {
188         Node* selectionNode = m_frame->selectionController()->selection().start().node();
189         if (enclosingNodeWithTag(selectionNode, olTag))
190             return Frame::trueTriState;
191     } else if (m_frame->selectionController()->isRange()) {
192         Node* startNode = enclosingNodeWithTag(m_frame->selectionController()->selection().start().node(), olTag);
193         Node* endNode = enclosingNodeWithTag(m_frame->selectionController()->selection().end().node(), olTag);
194         if (startNode && endNode && startNode == endNode)
195             return Frame::trueTriState;
196     }
197
198     return Frame::falseTriState;
199 }
200
201 // =============================================================================
202 //
203 // public editing commands
204 //
205 // =============================================================================
206
207 Editor::Editor(Frame* frame, PassRefPtr<EditorClient> client)
208     : m_frame(frame)
209     , m_client(client)
210     , m_deleteButtonController(new DeleteButtonController(frame))
211
212 }
213
214 Editor::~Editor()
215 {
216 }
217
218 void Editor::cut()
219 {
220     if (tryDHTMLCut())
221         return; // DHTML did the whole operation
222     if (!canCut()) {
223         systemBeep();
224         return;
225     }
226     
227     if (shouldDeleteRange(selectedRange())) {
228         writeSelectionToPasteboard(generalPasteboard());
229         deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
230     }
231 }
232
233 void Editor::copy()
234 {
235     if (tryDHTMLCopy())
236         return; // DHTML did the whole operation
237     if (!canCopy()) {
238         systemBeep();
239         return;
240     }
241     writeSelectionToPasteboard(generalPasteboard());
242 }
243
244 void Editor::paste()
245 {
246     if (tryDHTMLPaste())
247         return;     // DHTML did the whole operation
248     if (!canPaste())
249         return;
250     if (isSelectionRichlyEditable())
251         pasteWithPasteboard(generalPasteboard(), true);
252     else
253         pasteAsPlainTextWithPasteboard(generalPasteboard());
254 }
255
256 void Editor::performDelete()
257 {
258     if (!canDelete()) {
259         systemBeep();
260         return;
261     }
262     deleteSelection();
263 }
264
265 } // namespace WebCore