fc76347e5079f26bd373f5dbb928def9a00b0c1a
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / EditorClientGtk.cpp
1 /*
2  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> 
3  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4  * Copyright (C) 2006 Apple Computer, Inc.
5  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "EditorClientGtk.h"
33
34 #include "EditCommand.h"
35 #include "Editor.h"
36 #include "FocusController.h"
37 #include "Frame.h"
38 #include "KeyboardCodes.h"
39 #include "KeyboardEvent.h"
40 #include "NotImplemented.h"
41 #include "Page.h"
42 #include "PlatformKeyboardEvent.h"
43 #include "webkitprivate.h"
44
45 #include <stdio.h>
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 static void imContextCommitted(GtkIMContext* context, const char* str, EditorClient* client)
52 {
53     WebKitWebViewPrivate* pageData = WEBKIT_WEB_VIEW_GET_PRIVATE(client->m_page);
54     Frame* frame = pageData->corePage->focusController()->focusedOrMainFrame();
55     frame->editor()->insertTextWithoutSendingTextEvent(str, false);
56 }
57
58 bool EditorClient::shouldDeleteRange(Range*)
59 {
60     notImplemented();
61     return true;
62 }
63
64 bool EditorClient::shouldShowDeleteInterface(HTMLElement*)
65 {
66     return false;
67 }
68
69 bool EditorClient::isContinuousSpellCheckingEnabled()
70 {
71     notImplemented();
72     return false;
73 }
74
75 bool EditorClient::isGrammarCheckingEnabled()
76 {
77     notImplemented();
78     return false;
79 }
80
81 int EditorClient::spellCheckerDocumentTag()
82 {
83     notImplemented();
84     return 0;
85 }
86
87 bool EditorClient::shouldBeginEditing(WebCore::Range*)
88 {
89     notImplemented();
90     return true;
91 }
92
93 bool EditorClient::shouldEndEditing(WebCore::Range*)
94 {
95     notImplemented();
96     return true;
97 }
98
99 bool EditorClient::shouldInsertText(String, Range*, EditorInsertAction)
100 {
101     notImplemented();
102     return true;
103 }
104
105 bool EditorClient::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool)
106 {
107     notImplemented();
108     return true;
109 }
110
111 bool EditorClient::shouldApplyStyle(WebCore::CSSStyleDeclaration*,
112                                       WebCore::Range*)
113 {
114     notImplemented();
115     return true;
116 }
117
118 bool EditorClient::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*)
119 {
120     notImplemented();
121     return true;
122 }
123
124 void EditorClient::didBeginEditing()
125 {
126     notImplemented();
127 }
128
129 void EditorClient::respondToChangedContents()
130 {
131     notImplemented();
132 }
133
134 void EditorClient::respondToChangedSelection()
135 {
136     notImplemented();
137 }
138
139 void EditorClient::didEndEditing()
140 {
141     notImplemented();
142 }
143
144 void EditorClient::didWriteSelectionToPasteboard()
145 {
146     notImplemented();
147 }
148
149 void EditorClient::didSetSelectionTypesForPasteboard()
150 {
151     notImplemented();
152 }
153
154 bool EditorClient::isEditable()
155 {
156     return webkit_web_view_get_editable(m_page);
157 }
158
159 void EditorClient::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand>)
160 {
161     notImplemented();
162 }
163
164 void EditorClient::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand>)
165 {
166     notImplemented();
167 }
168
169 void EditorClient::clearUndoRedoOperations()
170 {
171     notImplemented();
172 }
173
174 bool EditorClient::canUndo() const
175 {
176     notImplemented();
177     return false;
178 }
179
180 bool EditorClient::canRedo() const
181 {
182     notImplemented();
183     return false;
184 }
185
186 void EditorClient::undo()
187 {
188     notImplemented();
189 }
190
191 void EditorClient::redo()
192 {
193     notImplemented();
194 }
195
196 bool EditorClient::shouldInsertNode(Node*, Range*, EditorInsertAction)
197 {
198     notImplemented();
199     return true;
200 }
201
202 void EditorClient::pageDestroyed()
203 {
204     delete this;
205 }
206
207 bool EditorClient::smartInsertDeleteEnabled()
208 {
209     notImplemented();
210     return false;
211 }
212
213 void EditorClient::toggleContinuousSpellChecking()
214 {
215     notImplemented();
216 }
217
218 void EditorClient::toggleGrammarChecking()
219 {
220 }
221
222 void EditorClient::handleKeyboardEvent(KeyboardEvent* event)
223 {
224     Frame* frame = core(m_page)->focusController()->focusedOrMainFrame();
225     if (!frame || !frame->document()->focusedNode())
226         return;
227
228     const PlatformKeyboardEvent* kevent = event->keyEvent();
229     if (!kevent || kevent->type() == PlatformKeyboardEvent::KeyUp)
230         return;
231
232     Node* start = frame->selectionController()->start().node();
233     if (!start)
234         return;
235
236     // FIXME: Use GtkBindingSet instead of this hard-coded switch
237     // http://bugs.webkit.org/show_bug.cgi?id=15911
238
239     if (start->isContentEditable()) {
240         switch (kevent->windowsVirtualKeyCode()) {
241             case VK_BACK:
242                 frame->editor()->deleteWithDirection(SelectionController::BACKWARD,
243                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity, false, true);
244                 break;
245             case VK_DELETE:
246                 frame->editor()->deleteWithDirection(SelectionController::FORWARD,
247                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity, false, true);
248                 break;
249             case VK_LEFT:
250                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
251                         SelectionController::LEFT,
252                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity,
253                         true);
254                 break;
255             case VK_RIGHT:
256                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
257                         SelectionController::RIGHT,
258                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity,
259                         true);
260                 break;
261             case VK_UP:
262                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
263                         SelectionController::BACKWARD,
264                         kevent->ctrlKey() ? ParagraphGranularity : LineGranularity,
265                         true);
266                 break;
267             case VK_DOWN:
268                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
269                         SelectionController::FORWARD,
270                         kevent->ctrlKey() ? ParagraphGranularity : LineGranularity,
271                         true);
272                 break;
273             case VK_PRIOR:  // PageUp
274                 frame->editor()->execCommand("MoveUpByPageAndModifyCaret");
275                 break;
276             case VK_NEXT:  // PageDown
277                 frame->editor()->execCommand("MoveDownByPageAndModifyCaret");
278                 break;
279             case VK_HOME:
280                 if (kevent->ctrlKey() && kevent->shiftKey())
281                     frame->editor()->execCommand("MoveToBeginningOfDocumentAndModifySelection");
282                 else if (kevent->ctrlKey())
283                     frame->editor()->execCommand("MoveToBeginningOfDocument");
284                 else if (kevent->shiftKey())
285                     frame->editor()->execCommand("MoveToBeginningOfLineAndModifySelection");
286                 else
287                     frame->editor()->execCommand("MoveToBeginningOfLine");
288                 break;
289             case VK_END:
290                 if (kevent->ctrlKey() && kevent->shiftKey())
291                     frame->editor()->execCommand("MoveToEndOfDocumentAndModifySelection");
292                 else if (kevent->ctrlKey())
293                     frame->editor()->execCommand("MoveToEndOfDocument");
294                 else if (kevent->shiftKey())
295                     frame->editor()->execCommand("MoveToEndOfLineAndModifySelection");
296                 else
297                     frame->editor()->execCommand("MoveToEndOfLine");
298                 break;
299             case VK_RETURN:
300                 frame->editor()->execCommand("InsertLineBreak");
301                 break;
302             case VK_TAB:
303                 return;
304             default:
305                 if (!kevent->ctrlKey() && !kevent->altKey() && !kevent->text().isEmpty()) {
306                     if (kevent->text().length() == 1) {
307                         UChar ch = kevent->text()[0];
308                         // Don't insert null or control characters as they can result in unexpected behaviour
309                         if (ch < ' ')
310                             break;
311                     }
312                     frame->editor()->insertText(kevent->text(), event);
313                 } else if (kevent->ctrlKey()) {
314                     switch (kevent->windowsVirtualKeyCode()) {
315                         case VK_B:
316                             frame->editor()->execCommand("ToggleBold");
317                             break;
318                         case VK_I:
319                             frame->editor()->execCommand("ToggleItalic");
320                             break;
321                         case VK_Y:
322                             frame->editor()->execCommand("Redo");
323                             break;
324                         case VK_Z:
325                             frame->editor()->execCommand("Undo");
326                             break;
327                         default:
328                             return;
329                     }
330                 } else return;
331         }
332     } else {
333         switch (kevent->windowsVirtualKeyCode()) {
334             case VK_UP:
335                 frame->editor()->execCommand("MoveUp");
336                 break;
337             case VK_DOWN:
338                 frame->editor()->execCommand("MoveDown");
339                 break;
340             case VK_PRIOR:  // PageUp
341                 frame->editor()->execCommand("MoveUpByPageAndModifyCaret");
342                 break;
343             case VK_NEXT:  // PageDown
344                 frame->editor()->execCommand("MoveDownByPageAndModifyCaret");
345                 break;
346             case VK_HOME:
347                 if (kevent->ctrlKey())
348                     frame->editor()->execCommand("MoveToBeginningOfDocument");
349                 break;
350             case VK_END:
351                 if (kevent->ctrlKey())
352                     frame->editor()->execCommand("MoveToEndOfDocument");
353                 break;
354             default:
355                 return;
356         }
357     }
358     event->setDefaultHandled();
359 }
360
361
362 void EditorClient::handleInputMethodKeydown(KeyboardEvent*)
363 {
364     notImplemented();
365 }
366
367 EditorClient::EditorClient(WebKitWebView* page)
368     : m_page(page)
369 {
370     WebKitWebViewPrivate* pageData = WEBKIT_WEB_VIEW_GET_PRIVATE(m_page);
371     g_signal_connect(pageData->imContext, "commit", G_CALLBACK(imContextCommitted), this);
372 }
373
374 EditorClient::~EditorClient()
375 {
376     WebKitWebViewPrivate* pageData = WEBKIT_WEB_VIEW_GET_PRIVATE(m_page);
377     g_signal_handlers_disconnect_by_func(pageData->imContext, (gpointer)imContextCommitted, this);
378 }
379
380 void EditorClient::textFieldDidBeginEditing(Element*)
381 {
382     gtk_im_context_focus_in(WEBKIT_WEB_VIEW_GET_PRIVATE(m_page)->imContext);
383 }
384
385 void EditorClient::textFieldDidEndEditing(Element*)
386 {
387     WebKitWebViewPrivate* pageData = WEBKIT_WEB_VIEW_GET_PRIVATE(m_page);
388
389     gtk_im_context_focus_out(pageData->imContext);
390 #ifdef MAEMO_CHANGES
391     hildon_gtk_im_context_hide(pageData->imContext);
392 #endif
393 }
394
395 void EditorClient::textDidChangeInTextField(Element*)
396 {
397     notImplemented();
398 }
399
400 bool EditorClient::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
401 {
402     notImplemented();
403     return false;
404 }
405
406 void EditorClient::textWillBeDeletedInTextField(Element*)
407 {
408     notImplemented();
409 }
410
411 void EditorClient::textDidChangeInTextArea(Element*)
412 {
413     notImplemented();
414 }
415
416 void EditorClient::ignoreWordInSpellDocument(const String&)
417 {
418     notImplemented();
419 }
420
421 void EditorClient::learnWord(const String&)
422 {
423     notImplemented();
424 }
425
426 void EditorClient::checkSpellingOfString(const UChar*, int, int*, int*)
427 {
428     notImplemented();
429 }
430
431 void EditorClient::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
432 {
433     notImplemented();
434 }
435
436 void EditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
437 {
438     notImplemented();
439 }
440
441 void EditorClient::updateSpellingUIWithMisspelledWord(const String&)
442 {
443     notImplemented();
444 }
445
446 void EditorClient::showSpellingUI(bool)
447 {
448     notImplemented();
449 }
450
451 bool EditorClient::spellingUIIsShowing()
452 {
453     notImplemented();
454     return false;
455 }
456
457 void EditorClient::getGuessesForWord(const String&, Vector<String>&)
458 {
459     notImplemented();
460 }
461
462 void EditorClient::setInputMethodState(bool)
463 {
464 }
465
466 }
467
468 // vim: ts=4 sw=4 et