• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include "config.h"
28 #include "EditorClientWx.h"
29 
30 #include "EditCommand.h"
31 #include "Editor.h"
32 #include "FocusController.h"
33 #include "Frame.h"
34 #include "FrameView.h"
35 #include "KeyboardEvent.h"
36 #include "KeyboardCodes.h"
37 #include "NotImplemented.h"
38 #include "Page.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "PlatformString.h"
41 #include "SelectionController.h"
42 
43 #include "WebFrame.h"
44 #include "WebFramePrivate.h"
45 #include "WebView.h"
46 #include "WebViewPrivate.h"
47 
48 #include <stdio.h>
49 
50 namespace WebCore {
51 
52 static const unsigned CtrlKey = 1 << 0;
53 static const unsigned AltKey = 1 << 1;
54 static const unsigned ShiftKey = 1 << 2;
55 
56 struct KeyDownEntry {
57     unsigned virtualKey;
58     unsigned modifiers;
59     const char* name;
60 };
61 
62 struct KeyPressEntry {
63     unsigned charCode;
64     unsigned modifiers;
65     const char* name;
66 };
67 
68 static const KeyDownEntry keyDownEntries[] = {
69     { VK_LEFT,   0,                  "MoveLeft"                                    },
70     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
71     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
72     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
73     { VK_RIGHT,  0,                  "MoveRight"                                   },
74     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
75     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
76     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
77     { VK_UP,     0,                  "MoveUp"                                      },
78     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
79     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
80     { VK_DOWN,   0,                  "MoveDown"                                    },
81     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
82     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
83     { VK_PRIOR,  0,                  "MovePageUp"                                  },
84     { VK_NEXT,   0,                  "MovePageDown"                                },
85     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
86     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
87     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
88     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
89 
90     { VK_END,    0,                  "MoveToEndOfLine"                             },
91     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
92     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
93     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
94 
95     { VK_BACK,   0,                  "DeleteBackward"                              },
96     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
97     { VK_DELETE, 0,                  "DeleteForward"                               },
98     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
99     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
100 
101     { 'B',       CtrlKey,            "ToggleBold"                                  },
102     { 'I',       CtrlKey,            "ToggleItalic"                                },
103 
104     { VK_ESCAPE, 0,                  "Cancel"                                      },
105     //FIXME: this'll never happen. We can trash it or make it a normal period
106     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
107     { VK_TAB,    0,                  "InsertTab"                                   },
108     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
109     { VK_RETURN, 0,                  "InsertNewline"                               },
110     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
111     { VK_RETURN, AltKey,             "InsertNewline"                               },
112     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
113     { 'A',       CtrlKey,            "SelectAll"                                   },
114     { 'Z',       CtrlKey,            "Undo"                                        },
115     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
116 };
117 
118 static const KeyPressEntry keyPressEntries[] = {
119     { '\t',   0,                  "InsertTab"                                   },
120     { '\t',   ShiftKey,           "InsertBacktab"                               },
121     { '\r',   0,                  "InsertNewline"                               },
122     { '\r',   CtrlKey,            "InsertNewline"                               },
123     { '\r',   AltKey,             "InsertNewline"                               },
124     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
125 };
126 
~EditorClientWx()127 EditorClientWx::~EditorClientWx()
128 {
129     m_page = NULL;
130 }
131 
setPage(Page * page)132 void EditorClientWx::setPage(Page* page)
133 {
134     m_page = page;
135 }
136 
pageDestroyed()137 void EditorClientWx::pageDestroyed()
138 {
139     delete this;
140 }
141 
shouldDeleteRange(Range *)142 bool EditorClientWx::shouldDeleteRange(Range*)
143 {
144     notImplemented();
145     return true;
146 }
147 
shouldShowDeleteInterface(HTMLElement *)148 bool EditorClientWx::shouldShowDeleteInterface(HTMLElement*)
149 {
150     notImplemented();
151     return false;
152 }
153 
smartInsertDeleteEnabled()154 bool EditorClientWx::smartInsertDeleteEnabled()
155 {
156     notImplemented();
157     return false;
158 }
159 
isSelectTrailingWhitespaceEnabled()160 bool EditorClientWx::isSelectTrailingWhitespaceEnabled()
161 {
162     notImplemented();
163     return false;
164 }
165 
isContinuousSpellCheckingEnabled()166 bool EditorClientWx::isContinuousSpellCheckingEnabled()
167 {
168     notImplemented();
169     return false;
170 }
171 
toggleContinuousSpellChecking()172 void EditorClientWx::toggleContinuousSpellChecking()
173 {
174     notImplemented();
175 }
176 
isGrammarCheckingEnabled()177 bool EditorClientWx::isGrammarCheckingEnabled()
178 {
179     notImplemented();
180     return false;
181 }
182 
toggleGrammarChecking()183 void EditorClientWx::toggleGrammarChecking()
184 {
185     notImplemented();
186 }
187 
spellCheckerDocumentTag()188 int EditorClientWx::spellCheckerDocumentTag()
189 {
190     notImplemented();
191     return 0;
192 }
193 
selectWordBeforeMenuEvent()194 bool EditorClientWx::selectWordBeforeMenuEvent()
195 {
196     notImplemented();
197     return false;
198 }
199 
isEditable()200 bool EditorClientWx::isEditable()
201 {
202     Frame* frame = m_page->focusController()->focusedOrMainFrame();
203 
204     if (frame) {
205         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
206         if (webKitWin)
207             return webKitWin->IsEditable();
208     }
209     return false;
210 }
211 
shouldBeginEditing(Range *)212 bool EditorClientWx::shouldBeginEditing(Range*)
213 {
214     notImplemented();
215     return true;
216 }
217 
shouldEndEditing(Range *)218 bool EditorClientWx::shouldEndEditing(Range*)
219 {
220     notImplemented();
221     return true;
222 }
223 
shouldInsertNode(Node *,Range *,EditorInsertAction)224 bool EditorClientWx::shouldInsertNode(Node*, Range*,
225                                        EditorInsertAction)
226 {
227     notImplemented();
228     return true;
229 }
230 
shouldInsertText(const String &,Range *,EditorInsertAction)231 bool EditorClientWx::shouldInsertText(const String&, Range*,
232                                        EditorInsertAction)
233 {
234     notImplemented();
235     return true;
236 }
237 
shouldApplyStyle(CSSStyleDeclaration *,Range *)238 bool EditorClientWx::shouldApplyStyle(CSSStyleDeclaration*,
239                                        Range*)
240 {
241     notImplemented();
242     return true;
243 }
244 
shouldMoveRangeAfterDelete(Range *,Range *)245 bool EditorClientWx::shouldMoveRangeAfterDelete(Range*, Range*)
246 {
247     notImplemented();
248     return true;
249 }
250 
shouldChangeSelectedRange(Range * fromRange,Range * toRange,EAffinity,bool stillSelecting)251 bool EditorClientWx::shouldChangeSelectedRange(Range* fromRange, Range* toRange,
252                                 EAffinity, bool stillSelecting)
253 {
254     notImplemented();
255     return true;
256 }
257 
didBeginEditing()258 void EditorClientWx::didBeginEditing()
259 {
260     notImplemented();
261 }
262 
respondToChangedContents()263 void EditorClientWx::respondToChangedContents()
264 {
265     notImplemented();
266 }
267 
didEndEditing()268 void EditorClientWx::didEndEditing()
269 {
270     notImplemented();
271 }
272 
didWriteSelectionToPasteboard()273 void EditorClientWx::didWriteSelectionToPasteboard()
274 {
275     notImplemented();
276 }
277 
didSetSelectionTypesForPasteboard()278 void EditorClientWx::didSetSelectionTypesForPasteboard()
279 {
280     notImplemented();
281 }
282 
registerCommandForUndo(PassRefPtr<EditCommand> command)283 void EditorClientWx::registerCommandForUndo(PassRefPtr<EditCommand> command)
284 {
285     Frame* frame = m_page->focusController()->focusedOrMainFrame();
286 
287     if (frame) {
288         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
289         if (webKitWin) {
290             webKitWin->GetMainFrame()->m_impl->undoStack.append(EditCommandWx(command));
291         }
292     }
293 }
294 
registerCommandForRedo(PassRefPtr<EditCommand> command)295 void EditorClientWx::registerCommandForRedo(PassRefPtr<EditCommand> command)
296 {
297     Frame* frame = m_page->focusController()->focusedOrMainFrame();
298 
299     if (frame) {
300         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
301         if (webKitWin) {
302             webKitWin->GetMainFrame()->m_impl->redoStack.insert(0, EditCommandWx(command));
303         }
304     }
305 }
306 
clearUndoRedoOperations()307 void EditorClientWx::clearUndoRedoOperations()
308 {
309     notImplemented();
310 }
311 
canUndo() const312 bool EditorClientWx::canUndo() const
313 {
314     Frame* frame = m_page->focusController()->focusedOrMainFrame();
315 
316     if (frame) {
317         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
318         if (webKitWin && webKitWin->GetMainFrame()) {
319             return webKitWin->GetMainFrame()->m_impl->undoStack.size() != 0;
320         }
321     }
322     return false;
323 }
324 
canRedo() const325 bool EditorClientWx::canRedo() const
326 {
327     Frame* frame = m_page->focusController()->focusedOrMainFrame();
328 
329     if (frame) {
330         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
331         if (webKitWin && webKitWin->GetMainFrame()) {
332             return webKitWin->GetMainFrame()->m_impl->redoStack.size() != 0;
333         }
334     }
335     return false;
336 }
337 
undo()338 void EditorClientWx::undo()
339 {
340     Frame* frame = m_page->focusController()->focusedOrMainFrame();
341 
342     if (frame) {
343         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
344         if (webKitWin && webKitWin->GetMainFrame()) {
345             webKitWin->GetMainFrame()->m_impl->undoStack.last().editCommand()->unapply();
346             webKitWin->GetMainFrame()->m_impl->undoStack.removeLast();
347         }
348     }
349 }
350 
redo()351 void EditorClientWx::redo()
352 {
353     Frame* frame = m_page->focusController()->focusedOrMainFrame();
354 
355     if (frame) {
356         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->platformWidget());
357         if (webKitWin && webKitWin->GetMainFrame()) {
358             webKitWin->GetMainFrame()->m_impl->redoStack.first().editCommand()->reapply();
359             webKitWin->GetMainFrame()->m_impl->redoStack.remove(0);
360         }
361     }
362 }
363 
handleEditingKeyboardEvent(KeyboardEvent * event)364 bool EditorClientWx::handleEditingKeyboardEvent(KeyboardEvent* event)
365 {
366     Node* node = event->target()->toNode();
367     ASSERT(node);
368     Frame* frame = node->document()->frame();
369     ASSERT(frame);
370 
371     const PlatformKeyboardEvent* keyEvent = event->keyEvent();
372 
373     //NB: this is what windows does, but they also have a keypress event for Alt+Enter which clearly won't get hit with this
374     if (!keyEvent || keyEvent->altKey())  // do not treat this as text input if Alt is down
375         return false;
376 
377     Editor::Command command = frame->editor()->command(interpretKeyEvent(event));
378 
379     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
380         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
381         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or if not to let a CHAR event be generated
382         // (e.g. Tab that inserts a Tab character, or Enter).
383         return !command.isTextInsertion() && command.execute(event);
384     }
385 
386      if (command.execute(event))
387         return true;
388 
389     // Don't insert null or control characters as they can result in unexpected behaviour
390     if (event->charCode() < ' ')
391         return false;
392 
393     return frame->editor()->insertText(event->keyEvent()->text(), event);
394 }
395 
interpretKeyEvent(const KeyboardEvent * evt)396 const char* EditorClientWx::interpretKeyEvent(const KeyboardEvent* evt)
397 {
398     ASSERT(evt->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown || evt->keyEvent()->type() == PlatformKeyboardEvent::Char);
399 
400     static HashMap<int, const char*>* keyDownCommandsMap = 0;
401     static HashMap<int, const char*>* keyPressCommandsMap = 0;
402 
403     if (!keyDownCommandsMap) {
404         keyDownCommandsMap = new HashMap<int, const char*>;
405         keyPressCommandsMap = new HashMap<int, const char*>;
406 
407         for (unsigned i = 0; i < WXSIZEOF(keyDownEntries); i++)
408             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
409 
410         for (unsigned i = 0; i < WXSIZEOF(keyPressEntries); i++)
411             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
412     }
413 
414     unsigned modifiers = 0;
415     if (evt->shiftKey())
416         modifiers |= ShiftKey;
417     if (evt->altKey())
418         modifiers |= AltKey;
419     if (evt->ctrlKey())
420         modifiers |= CtrlKey;
421 
422     if (evt->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown) {
423         int mapKey = modifiers << 16 | evt->keyCode();
424         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
425     }
426 
427     int mapKey = modifiers << 16 | evt->charCode();
428     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
429 }
430 
431 
handleInputMethodKeydown(KeyboardEvent * event)432 void EditorClientWx::handleInputMethodKeydown(KeyboardEvent* event)
433 {
434 // NOTE: we don't currently need to handle this. When key events occur,
435 // both this method and handleKeyboardEvent get a chance at handling them.
436 // We might use this method later on for IME-specific handling.
437 }
438 
handleKeyboardEvent(KeyboardEvent * event)439 void EditorClientWx::handleKeyboardEvent(KeyboardEvent* event)
440 {
441     if (handleEditingKeyboardEvent(event))
442         event->setDefaultHandled();
443 }
444 
textFieldDidBeginEditing(Element *)445 void EditorClientWx::textFieldDidBeginEditing(Element*)
446 {
447     notImplemented();
448 }
449 
textFieldDidEndEditing(Element *)450 void EditorClientWx::textFieldDidEndEditing(Element*)
451 {
452     notImplemented();
453 }
454 
textDidChangeInTextField(Element *)455 void EditorClientWx::textDidChangeInTextField(Element*)
456 {
457     notImplemented();
458 }
459 
doTextFieldCommandFromEvent(Element *,KeyboardEvent *)460 bool EditorClientWx::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
461 {
462     notImplemented();
463     return false;
464 }
465 
textWillBeDeletedInTextField(Element *)466 void EditorClientWx::textWillBeDeletedInTextField(Element*)
467 {
468     notImplemented();
469 }
470 
textDidChangeInTextArea(Element *)471 void EditorClientWx::textDidChangeInTextArea(Element*)
472 {
473     notImplemented();
474 }
475 
respondToChangedSelection()476 void EditorClientWx::respondToChangedSelection()
477 {
478     notImplemented();
479 }
480 
ignoreWordInSpellDocument(const String &)481 void EditorClientWx::ignoreWordInSpellDocument(const String&)
482 {
483     notImplemented();
484 }
485 
learnWord(const String &)486 void EditorClientWx::learnWord(const String&)
487 {
488     notImplemented();
489 }
490 
checkSpellingOfString(const UChar *,int length,int * misspellingLocation,int * misspellingLength)491 void EditorClientWx::checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength)
492 {
493     notImplemented();
494 }
495 
checkGrammarOfString(const UChar *,int length,Vector<GrammarDetail> &,int * badGrammarLocation,int * badGrammarLength)496 void EditorClientWx::checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength)
497 {
498     notImplemented();
499 }
500 
updateSpellingUIWithGrammarString(const String &,const GrammarDetail & detail)501 void EditorClientWx::updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail)
502 {
503     notImplemented();
504 }
505 
updateSpellingUIWithMisspelledWord(const String &)506 void EditorClientWx::updateSpellingUIWithMisspelledWord(const String&)
507 {
508     notImplemented();
509 }
510 
showSpellingUI(bool show)511 void EditorClientWx::showSpellingUI(bool show)
512 {
513     notImplemented();
514 }
515 
spellingUIIsShowing()516 bool EditorClientWx::spellingUIIsShowing()
517 {
518     notImplemented();
519     return false;
520 }
521 
getGuessesForWord(const String &,Vector<String> & guesses)522 void EditorClientWx::getGuessesForWord(const String&, Vector<String>& guesses)
523 {
524     notImplemented();
525 }
526 
getAutoCorrectSuggestionForMisspelledWord(const WebCore::String &)527 String EditorClientWx::getAutoCorrectSuggestionForMisspelledWord(const WebCore::String&)
528 {
529     notImplemented();
530     return String();
531 }
532 
setInputMethodState(bool enabled)533 void EditorClientWx::setInputMethodState(bool enabled)
534 {
535     notImplemented();
536 }
537 
538 }
539