1 /*
2 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
3 * Copyright (C) 2008 Nuanti Ltd.
4 * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
5 * Copyright (C) 2009-2010 ProFUSION embedded systems
6 * Copyright (C) 2009-2010 Samsung Electronics
7 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "config.h"
25 #include "EditorClientWinCE.h"
26
27 #include "EditCommand.h"
28 #include "Frame.h"
29 #include "KeyboardEvent.h"
30 #include "NotImplemented.h"
31 #include "PlatformKeyboardEvent.h"
32 #include "Settings.h"
33
34 using namespace WebCore;
35
36 namespace WebKit {
37
EditorClientWinCE(WebView * webView)38 EditorClientWinCE::EditorClientWinCE(WebView* webView)
39 : m_webView(webView)
40 {
41 }
42
~EditorClientWinCE()43 EditorClientWinCE::~EditorClientWinCE()
44 {
45 }
46
setInputMethodState(bool active)47 void EditorClientWinCE::setInputMethodState(bool active)
48 {
49 notImplemented();
50 }
51
shouldDeleteRange(Range *)52 bool EditorClientWinCE::shouldDeleteRange(Range*)
53 {
54 notImplemented();
55 return true;
56 }
57
shouldShowDeleteInterface(HTMLElement *)58 bool EditorClientWinCE::shouldShowDeleteInterface(HTMLElement*)
59 {
60 return false;
61 }
62
isContinuousSpellCheckingEnabled()63 bool EditorClientWinCE::isContinuousSpellCheckingEnabled()
64 {
65 notImplemented();
66 return false;
67 }
68
isGrammarCheckingEnabled()69 bool EditorClientWinCE::isGrammarCheckingEnabled()
70 {
71 notImplemented();
72 return false;
73 }
74
spellCheckerDocumentTag()75 int EditorClientWinCE::spellCheckerDocumentTag()
76 {
77 notImplemented();
78 return 0;
79 }
80
shouldBeginEditing(WebCore::Range *)81 bool EditorClientWinCE::shouldBeginEditing(WebCore::Range*)
82 {
83 notImplemented();
84 return true;
85 }
86
shouldEndEditing(WebCore::Range *)87 bool EditorClientWinCE::shouldEndEditing(WebCore::Range*)
88 {
89 notImplemented();
90 return true;
91 }
92
shouldInsertText(const String &,Range *,EditorInsertAction)93 bool EditorClientWinCE::shouldInsertText(const String&, Range*, EditorInsertAction)
94 {
95 notImplemented();
96 return true;
97 }
98
shouldChangeSelectedRange(Range *,Range *,EAffinity,bool)99 bool EditorClientWinCE::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool)
100 {
101 notImplemented();
102 return true;
103 }
104
shouldApplyStyle(WebCore::CSSStyleDeclaration *,WebCore::Range *)105 bool EditorClientWinCE::shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*)
106 {
107 notImplemented();
108 return true;
109 }
110
shouldMoveRangeAfterDelete(WebCore::Range *,WebCore::Range *)111 bool EditorClientWinCE::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*)
112 {
113 notImplemented();
114 return true;
115 }
116
didBeginEditing()117 void EditorClientWinCE::didBeginEditing()
118 {
119 notImplemented();
120 }
121
respondToChangedContents()122 void EditorClientWinCE::respondToChangedContents()
123 {
124 notImplemented();
125 }
126
respondToChangedSelection()127 void EditorClientWinCE::respondToChangedSelection()
128 {
129 notImplemented();
130 }
131
didEndEditing()132 void EditorClientWinCE::didEndEditing()
133 {
134 notImplemented();
135 }
136
didWriteSelectionToPasteboard()137 void EditorClientWinCE::didWriteSelectionToPasteboard()
138 {
139 notImplemented();
140 }
141
didSetSelectionTypesForPasteboard()142 void EditorClientWinCE::didSetSelectionTypesForPasteboard()
143 {
144 notImplemented();
145 }
146
registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> command)147 void EditorClientWinCE::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> command)
148 {
149 notImplemented();
150 }
151
registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand> command)152 void EditorClientWinCE::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand> command)
153 {
154 notImplemented();
155 }
156
clearUndoRedoOperations()157 void EditorClientWinCE::clearUndoRedoOperations()
158 {
159 notImplemented();
160 }
161
canCopyCut(bool defaultValue) const162 bool EditorClientWinCE::canCopyCut(bool defaultValue) const
163 {
164 return defaultValue;
165 }
166
canPaste(bool defaultValue) const167 bool EditorClientWinCE::canPaste(bool defaultValue) const
168 {
169 return defaultValue;
170 }
171
canUndo() const172 bool EditorClientWinCE::canUndo() const
173 {
174 notImplemented();
175 return false;
176 }
177
canRedo() const178 bool EditorClientWinCE::canRedo() const
179 {
180 notImplemented();
181 return false;
182 }
183
undo()184 void EditorClientWinCE::undo()
185 {
186 notImplemented();
187 }
188
redo()189 void EditorClientWinCE::redo()
190 {
191 notImplemented();
192 }
193
shouldInsertNode(Node *,Range *,EditorInsertAction)194 bool EditorClientWinCE::shouldInsertNode(Node*, Range*, EditorInsertAction)
195 {
196 notImplemented();
197 return true;
198 }
199
pageDestroyed()200 void EditorClientWinCE::pageDestroyed()
201 {
202 delete this;
203 }
204
smartInsertDeleteEnabled()205 bool EditorClientWinCE::smartInsertDeleteEnabled()
206 {
207 notImplemented();
208 return false;
209 }
210
isSelectTrailingWhitespaceEnabled()211 bool EditorClientWinCE::isSelectTrailingWhitespaceEnabled()
212 {
213 notImplemented();
214 return false;
215 }
216
toggleContinuousSpellChecking()217 void EditorClientWinCE::toggleContinuousSpellChecking()
218 {
219 notImplemented();
220 }
221
toggleGrammarChecking()222 void EditorClientWinCE::toggleGrammarChecking()
223 {
224 notImplemented();
225 }
226
227 static const unsigned CtrlKey = 1 << 0;
228 static const unsigned AltKey = 1 << 1;
229 static const unsigned ShiftKey = 1 << 2;
230
231 struct KeyDownEntry {
232 unsigned virtualKey;
233 unsigned modifiers;
234 const char* name;
235 };
236
237 struct KeyPressEntry {
238 unsigned charCode;
239 unsigned modifiers;
240 const char* name;
241 };
242
243 static const KeyDownEntry keyDownEntries[] = {
244 { VK_LEFT, 0, "MoveLeft" },
245 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" },
246 { VK_LEFT, CtrlKey, "MoveWordLeft" },
247 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" },
248 { VK_RIGHT, 0, "MoveRight" },
249 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" },
250 { VK_RIGHT, CtrlKey, "MoveWordRight" },
251 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" },
252 { VK_UP, 0, "MoveUp" },
253 { VK_UP, ShiftKey, "MoveUpAndModifySelection" },
254 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" },
255 { VK_DOWN, 0, "MoveDown" },
256 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" },
257 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" },
258 { VK_PRIOR, 0, "MovePageUp" },
259 { VK_NEXT, 0, "MovePageDown" },
260 { VK_HOME, 0, "MoveToBeginningOfLine" },
261 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" },
262 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" },
263 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
264
265 { VK_END, 0, "MoveToEndOfLine" },
266 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" },
267 { VK_END, CtrlKey, "MoveToEndOfDocument" },
268 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" },
269
270 { VK_BACK, 0, "DeleteBackward" },
271 { VK_BACK, ShiftKey, "DeleteBackward" },
272 { VK_DELETE, 0, "DeleteForward" },
273 { VK_BACK, CtrlKey, "DeleteWordBackward" },
274 { VK_DELETE, CtrlKey, "DeleteWordForward" },
275
276 { 'B', CtrlKey, "ToggleBold" },
277 { 'I', CtrlKey, "ToggleItalic" },
278
279 { VK_ESCAPE, 0, "Cancel" },
280 { VK_TAB, 0, "InsertTab" },
281 { VK_TAB, ShiftKey, "InsertBacktab" },
282 { VK_RETURN, 0, "InsertNewline" },
283 { VK_RETURN, CtrlKey, "InsertNewline" },
284 { VK_RETURN, AltKey, "InsertNewline" },
285 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
286
287 // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
288 // in the application or in WebKit. We chose WebKit for now.
289 { 'C', CtrlKey, "Copy" },
290 { 'V', CtrlKey, "Paste" },
291 { 'X', CtrlKey, "Cut" },
292 { 'A', CtrlKey, "SelectAll" },
293 { VK_INSERT, CtrlKey, "Copy" },
294 { VK_DELETE, ShiftKey, "Cut" },
295 { VK_INSERT, ShiftKey, "Paste" },
296 { 'Z', CtrlKey, "Undo" },
297 { 'Z', CtrlKey | ShiftKey, "Redo" }
298 };
299
300 static const KeyPressEntry keyPressEntries[] = {
301 { '\t', 0, "InsertTab" },
302 { '\t', ShiftKey, "InsertBacktab" },
303 { '\r', 0, "InsertNewline" },
304 { '\r', CtrlKey, "InsertNewline" },
305 { '\r', AltKey, "InsertNewline" },
306 { '\r', AltKey | ShiftKey, "InsertNewline" }
307 };
308
interpretKeyEvent(const KeyboardEvent * event)309 const char* EditorClientWinCE::interpretKeyEvent(const KeyboardEvent* event)
310 {
311 ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
312
313 static HashMap<int, const char*>* keyDownCommandsMap = 0;
314 static HashMap<int, const char*>* keyPressCommandsMap = 0;
315
316 if (!keyDownCommandsMap) {
317 keyDownCommandsMap = new HashMap<int, const char*>;
318 keyPressCommandsMap = new HashMap<int, const char*>;
319
320 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
321 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
322
323 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
324 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
325 }
326
327 unsigned modifiers = 0;
328 if (event->shiftKey())
329 modifiers |= ShiftKey;
330 if (event->altKey())
331 modifiers |= AltKey;
332 if (event->ctrlKey())
333 modifiers |= CtrlKey;
334
335 if (event->type() == eventNames().keydownEvent) {
336 int mapKey = modifiers << 16 | event->keyCode();
337 return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
338 }
339
340 int mapKey = modifiers << 16 | event->charCode();
341 return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
342 }
343
handleEditingKeyboardEvent(KeyboardEvent * event)344 bool EditorClientWinCE::handleEditingKeyboardEvent(KeyboardEvent* event)
345 {
346 Node* node = event->target()->toNode();
347 ASSERT(node);
348 Frame* frame = node->document()->frame();
349 ASSERT(frame);
350
351 const PlatformKeyboardEvent* keyEvent = event->keyEvent();
352 if (!keyEvent)
353 return false;
354
355 bool caretBrowsing = frame->settings()->caretBrowsingEnabled();
356 if (caretBrowsing) {
357 switch (keyEvent->windowsVirtualKeyCode()) {
358 case VK_LEFT:
359 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
360 DirectionLeft,
361 keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
362 true);
363 return true;
364 case VK_RIGHT:
365 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
366 DirectionRight,
367 keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
368 true);
369 return true;
370 case VK_UP:
371 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
372 DirectionBackward,
373 keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
374 true);
375 return true;
376 case VK_DOWN:
377 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
378 DirectionForward,
379 keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
380 true);
381 return true;
382 }
383 }
384
385 Editor::Command command = frame->editor()->command(interpretKeyEvent(event));
386
387 if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
388 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
389 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
390 // (e.g. Tab that inserts a Tab character, or Enter).
391 return !command.isTextInsertion() && command.execute(event);
392 }
393
394 if (command.execute(event))
395 return true;
396
397 // Don't insert null or control characters as they can result in unexpected behaviour
398 if (event->charCode() < ' ')
399 return false;
400
401 // Don't insert anything if a modifier is pressed
402 if (keyEvent->ctrlKey() || keyEvent->altKey())
403 return false;
404
405 return frame->editor()->insertText(event->keyEvent()->text(), event);
406 }
407
handleKeyboardEvent(KeyboardEvent * event)408 void EditorClientWinCE::handleKeyboardEvent(KeyboardEvent* event)
409 {
410 if (handleEditingKeyboardEvent(event))
411 event->setDefaultHandled();
412 }
413
handleInputMethodKeydown(KeyboardEvent * event)414 void EditorClientWinCE::handleInputMethodKeydown(KeyboardEvent* event)
415 {
416 notImplemented();
417 }
418
textFieldDidBeginEditing(Element *)419 void EditorClientWinCE::textFieldDidBeginEditing(Element*)
420 {
421 }
422
textFieldDidEndEditing(Element *)423 void EditorClientWinCE::textFieldDidEndEditing(Element*)
424 {
425 }
426
textDidChangeInTextField(Element *)427 void EditorClientWinCE::textDidChangeInTextField(Element*)
428 {
429 }
430
doTextFieldCommandFromEvent(Element *,KeyboardEvent *)431 bool EditorClientWinCE::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
432 {
433 return false;
434 }
435
textWillBeDeletedInTextField(Element *)436 void EditorClientWinCE::textWillBeDeletedInTextField(Element*)
437 {
438 notImplemented();
439 }
440
textDidChangeInTextArea(Element *)441 void EditorClientWinCE::textDidChangeInTextArea(Element*)
442 {
443 notImplemented();
444 }
445
ignoreWordInSpellDocument(const String & text)446 void EditorClientWinCE::ignoreWordInSpellDocument(const String& text)
447 {
448 notImplemented();
449 }
450
learnWord(const String & text)451 void EditorClientWinCE::learnWord(const String& text)
452 {
453 notImplemented();
454 }
455
checkSpellingOfString(const UChar * text,int length,int * misspellingLocation,int * misspellingLength)456 void EditorClientWinCE::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
457 {
458 notImplemented();
459 }
460
getAutoCorrectSuggestionForMisspelledWord(const String & inputWord)461 String EditorClientWinCE::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord)
462 {
463 // This method can be implemented using customized algorithms for the particular browser.
464 // Currently, it computes an empty string.
465 return String();
466 }
467
checkGrammarOfString(const UChar *,int,Vector<GrammarDetail> &,int *,int *)468 void EditorClientWinCE::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
469 {
470 notImplemented();
471 }
472
updateSpellingUIWithGrammarString(const String &,const GrammarDetail &)473 void EditorClientWinCE::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
474 {
475 notImplemented();
476 }
477
updateSpellingUIWithMisspelledWord(const String &)478 void EditorClientWinCE::updateSpellingUIWithMisspelledWord(const String&)
479 {
480 notImplemented();
481 }
482
showSpellingUI(bool)483 void EditorClientWinCE::showSpellingUI(bool)
484 {
485 notImplemented();
486 }
487
spellingUIIsShowing()488 bool EditorClientWinCE::spellingUIIsShowing()
489 {
490 notImplemented();
491 return false;
492 }
493
getGuessesForWord(const String & word,const String & context,WTF::Vector<String> & guesses)494 void EditorClientWinCE::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses)
495 {
496 notImplemented();
497 }
498
willSetInputMethodState()499 void EditorClientWinCE::willSetInputMethodState()
500 {
501 notImplemented();
502 }
503
504 } // namespace WebKit
505