OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebKit / win / WebCoreSupport / WebEditorClient.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2011 Apple 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 "WebKitDLL.h"
28 #include "WebEditorClient.h"
29
30 #include "WebKit.h"
31 #include "WebNotification.h"
32 #include "WebNotificationCenter.h"
33 #include "WebView.h"
34 #include "DOMCoreClasses.h"
35 #include <WebCore/BString.h>
36 #include <WebCore/Document.h>
37 #include <WebCore/EditCommand.h>
38 #include <WebCore/HTMLElement.h>
39 #include <WebCore/HTMLInputElement.h>
40 #include <WebCore/HTMLNames.h>
41 #include <WebCore/KeyboardEvent.h>
42 #include <WebCore/LocalizedStrings.h>
43 #include <WebCore/NotImplemented.h>
44 #include <WebCore/PlatformKeyboardEvent.h>
45 #include <WebCore/Range.h>
46 #include <WebCore/UserTypingGestureIndicator.h>
47
48 using namespace WebCore;
49 using namespace HTMLNames;
50
51 // {09A11D2B-FAFB-4ca0-A6F7-791EE8932C88}
52 static const GUID IID_IWebUndoCommand = 
53 { 0x9a11d2b, 0xfafb, 0x4ca0, { 0xa6, 0xf7, 0x79, 0x1e, 0xe8, 0x93, 0x2c, 0x88 } };
54
55 class IWebUndoCommand : public IUnknown {
56 public:
57     virtual void execute() = 0;
58 };
59
60 // WebEditorUndoTarget -------------------------------------------------------------
61
62 class WebEditorUndoTarget : public IWebUndoTarget
63 {
64 public:
65     WebEditorUndoTarget();
66
67     // IUnknown
68     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
69     virtual ULONG STDMETHODCALLTYPE AddRef(void);
70     virtual ULONG STDMETHODCALLTYPE Release(void);
71
72     // IWebUndoTarget
73     virtual HRESULT STDMETHODCALLTYPE invoke( 
74         /* [in] */ BSTR actionName,
75         /* [in] */ IUnknown *obj);
76
77 private:
78     ULONG m_refCount;
79 };
80
81 WebEditorUndoTarget::WebEditorUndoTarget()
82 : m_refCount(1)
83 {
84 }
85
86 HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::QueryInterface(REFIID riid, void** ppvObject)
87 {
88     *ppvObject = 0;
89     if (IsEqualGUID(riid, IID_IUnknown))
90         *ppvObject = static_cast<IWebUndoTarget*>(this);
91     else if (IsEqualGUID(riid, IID_IWebUndoTarget))
92         *ppvObject = static_cast<IWebUndoTarget*>(this);
93     else
94         return E_NOINTERFACE;
95
96     AddRef();
97     return S_OK;
98 }
99
100 ULONG STDMETHODCALLTYPE WebEditorUndoTarget::AddRef(void)
101 {
102     return ++m_refCount;
103 }
104
105 ULONG STDMETHODCALLTYPE WebEditorUndoTarget::Release(void)
106 {
107     ULONG newRef = --m_refCount;
108     if (!newRef)
109         delete(this);
110
111     return newRef;
112 }
113
114 HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::invoke( 
115     /* [in] */ BSTR /*actionName*/,
116     /* [in] */ IUnknown *obj)
117 {
118     IWebUndoCommand* undoCommand = 0;
119     if (SUCCEEDED(obj->QueryInterface(IID_IWebUndoCommand, (void**)&undoCommand))) {
120         undoCommand->execute();
121         undoCommand->Release();
122     }
123     return S_OK;
124 }
125
126 // WebEditorClient ------------------------------------------------------------------
127
128 WebEditorClient::WebEditorClient(WebView* webView)
129     : m_webView(webView)
130     , m_undoTarget(0)
131 {
132     m_undoTarget = new WebEditorUndoTarget();
133 }
134
135 WebEditorClient::~WebEditorClient()
136 {
137     if (m_undoTarget)
138         m_undoTarget->Release();
139 }
140
141 void WebEditorClient::pageDestroyed()
142 {
143     delete this;
144 }
145
146 bool WebEditorClient::isContinuousSpellCheckingEnabled()
147 {
148     BOOL enabled;
149     if (FAILED(m_webView->isContinuousSpellCheckingEnabled(&enabled)))
150         return false;
151     return !!enabled;
152 }
153
154 void WebEditorClient::toggleContinuousSpellChecking()
155 {
156     m_webView->toggleContinuousSpellChecking(0);
157 }
158
159 bool WebEditorClient::isGrammarCheckingEnabled()
160 {
161     BOOL enabled;
162     if (FAILED(m_webView->isGrammarCheckingEnabled(&enabled)))
163         return false;
164     return !!enabled;
165 }
166
167 void WebEditorClient::toggleGrammarChecking()
168 {
169     m_webView->toggleGrammarChecking(0);
170 }
171
172 static void initViewSpecificSpelling(IWebViewEditing* viewEditing)
173 {
174     // we just use this as a flag to indicate that we've spell checked the document
175     // and need to close the spell checker out when the view closes.
176     int tag;
177     viewEditing->spellCheckerDocumentTag(&tag);
178 }
179
180 int WebEditorClient::spellCheckerDocumentTag()
181 {
182     // we don't use the concept of spelling tags
183     notImplemented();
184     ASSERT_NOT_REACHED();
185     return 0;
186 }
187
188 bool WebEditorClient::shouldBeginEditing(Range*)
189 {
190     notImplemented();
191     return true;
192 }
193
194 bool WebEditorClient::shouldEndEditing(Range*)
195 {
196     notImplemented();
197     return true;
198 }
199
200 void WebEditorClient::didBeginEditing()
201 {
202     notImplemented();
203 }
204
205 void WebEditorClient::respondToChangedContents()
206 {
207     notImplemented();
208 }
209
210 void WebEditorClient::respondToChangedSelection()
211 {
212     m_webView->selectionChanged();
213
214     static BSTR webViewDidChangeSelectionNotificationName = SysAllocString(WebViewDidChangeSelectionNotification);
215     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
216     notifyCenter->postNotificationName(webViewDidChangeSelectionNotificationName, static_cast<IWebView*>(m_webView), 0);
217 }
218
219 void WebEditorClient::didEndEditing()
220 {
221     notImplemented();
222 }
223
224 void WebEditorClient::didWriteSelectionToPasteboard()
225 {
226     notImplemented();
227 }
228
229 void WebEditorClient::didSetSelectionTypesForPasteboard()
230 {
231     notImplemented();
232 }
233
234 bool WebEditorClient::shouldDeleteRange(Range* /*range*/)
235 {
236     notImplemented(); 
237     return true; 
238
239     // FIXME: calling m_webView->editingDelegate() will cause an assertion failure so we don't want to enable this code until that's implemented. 
240     //BOOL result = false;
241     //IWebViewEditingDelegate* editingDelegate;
242     //// FIXME: DOMRange needs to be implemented before anything meaningful can be done here
243     //IDOMRange* domRange(0);
244     //if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) {
245     //    editingDelegate->shouldDeleteDOMRange(m_webView, domRange, &result);
246     //    editingDelegate->Release();
247     //}
248     //return !!result;
249 }
250
251 bool WebEditorClient::shouldInsertNode(Node* /*node*/, Range* /*replacingRange*/, EditorInsertAction /*givenAction*/)
252
253     notImplemented(); 
254     return true; 
255 }
256
257 bool WebEditorClient::shouldInsertText(const String& /*str*/, Range* /* replacingRange */, EditorInsertAction /*givenAction*/)
258 {     
259     notImplemented(); 
260     return true; 
261
262     // FIXME: calling m_webView->editingDelegate() will cause an assertion failure so we don't want to enable this code until that's implemented. 
263     //BOOL result = false;
264     //IWebViewEditingDelegate* editingDelegate;
265     //// FIXME: DOMRange needs to be implemented before anything meaningful can be done here
266     //IDOMRange* domRange(0); // make a DOMRange from replacingRange
267     //BString text(str);
268     //if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) {
269     //    editingDelegate->shouldInsertText(m_webView, text, domRange, (WebViewInsertAction) givenAction, &result);
270     //    editingDelegate->Release();
271     //}
272     //return !!result;
273 }
274
275 //bool WebEditorClient::shouldChangeSelectedRange(Range *currentRange, Range *toProposedRange, SelectionAffinity selectionAffinity, bool stillSelecting)
276 //{ notImplemented(); return false; }
277
278 bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* /*style*/, Range* /*toElementsInDOMRange*/)
279 { notImplemented(); return true; }
280
281 bool WebEditorClient::shouldMoveRangeAfterDelete(Range* /*range*/, Range* /*rangeToBeReplaced*/)
282 { notImplemented(); return true; }
283
284 bool WebEditorClient::shouldChangeTypingStyle(CSSStyleDeclaration* /*currentStyle*/, CSSStyleDeclaration* /*toProposedStyle*/)
285 { notImplemented(); return false; }
286
287 void WebEditorClient::webViewDidChangeTypingStyle(WebNotification* /*notification*/)
288 {  notImplemented(); }
289
290 void WebEditorClient::webViewDidChangeSelection(WebNotification* /*notification*/)
291 {  notImplemented(); }
292
293 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* /*element*/)
294 { notImplemented(); return false; }
295
296 bool WebEditorClient::smartInsertDeleteEnabled(void)
297
298     BOOL enabled = FALSE; 
299     m_webView->smartInsertDeleteEnabled(&enabled);
300     return !!enabled;
301 }
302
303 bool WebEditorClient::isSelectTrailingWhitespaceEnabled(void)
304 {
305     BOOL enabled = FALSE;
306     m_webView->isSelectTrailingWhitespaceEnabled(&enabled);
307     return !!enabled;
308 }
309
310 bool WebEditorClient::shouldChangeSelectedRange(WebCore::Range*, WebCore::Range*, WebCore::EAffinity, bool)
311 { notImplemented(); return true; }
312
313 void WebEditorClient::textFieldDidBeginEditing(Element* e)
314 {
315     IWebFormDelegate* formDelegate;
316     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
317         IDOMElement* domElement = DOMElement::createInstance(e);
318         if (domElement) {
319             IDOMHTMLInputElement* domInputElement;
320             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
321                 formDelegate->textFieldDidBeginEditing(domInputElement, kit(e->document()->frame()));
322                 domInputElement->Release();
323             }
324             domElement->Release();
325         }
326         formDelegate->Release();
327     }
328 }
329
330 void WebEditorClient::textFieldDidEndEditing(Element* e)
331 {
332     IWebFormDelegate* formDelegate;
333     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
334         IDOMElement* domElement = DOMElement::createInstance(e);
335         if (domElement) {
336             IDOMHTMLInputElement* domInputElement;
337             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
338                 formDelegate->textFieldDidEndEditing(domInputElement, kit(e->document()->frame()));
339                 domInputElement->Release();
340             }
341             domElement->Release();
342         }
343         formDelegate->Release();
344     }
345 }
346
347 void WebEditorClient::textDidChangeInTextField(Element* e)
348 {
349     if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != e)
350         return;
351
352     IWebFormDelegate* formDelegate;
353     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
354         IDOMElement* domElement = DOMElement::createInstance(e);
355         if (domElement) {
356             IDOMHTMLInputElement* domInputElement;
357             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
358                 formDelegate->textDidChangeInTextField(domInputElement, kit(e->document()->frame()));
359                 domInputElement->Release();
360             }
361             domElement->Release();
362         }
363         formDelegate->Release();
364     }
365 }
366
367 bool WebEditorClient::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
368 {
369     BOOL result = FALSE;
370     IWebFormDelegate* formDelegate;
371     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
372         IDOMElement* domElement = DOMElement::createInstance(e);
373         if (domElement) {
374             IDOMHTMLInputElement* domInputElement;
375             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
376                 String command = m_webView->interpretKeyEvent(ke);
377                 // We allow empty commands here because the app code actually depends on this being called for all key presses.
378                 // We may want to revisit this later because it doesn't really make sense to send an empty command.
379                 formDelegate->doPlatformCommand(domInputElement, BString(command), kit(e->document()->frame()), &result);
380                 domInputElement->Release();
381             }
382             domElement->Release();
383         }
384         formDelegate->Release();
385     }
386     return !!result;
387 }
388
389 void WebEditorClient::textWillBeDeletedInTextField(Element* e)
390 {
391     // We're using the deleteBackward command for all deletion operations since the autofill code treats all deletions the same way.
392     IWebFormDelegate* formDelegate;
393     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
394         IDOMElement* domElement = DOMElement::createInstance(e);
395         if (domElement) {
396             IDOMHTMLInputElement* domInputElement;
397             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
398                 BOOL result;
399                 formDelegate->doPlatformCommand(domInputElement, BString(L"DeleteBackward"), kit(e->document()->frame()), &result);
400                 domInputElement->Release();
401             }
402             domElement->Release();
403         }
404         formDelegate->Release();
405     }
406 }
407
408 void WebEditorClient::textDidChangeInTextArea(Element* e)
409 {
410     IWebFormDelegate* formDelegate;
411     if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
412         IDOMElement* domElement = DOMElement::createInstance(e);
413         if (domElement) {
414             IDOMHTMLTextAreaElement* domTextAreaElement;
415             if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLTextAreaElement, (void**)&domTextAreaElement))) {
416                 formDelegate->textDidChangeInTextArea(domTextAreaElement, kit(e->document()->frame()));
417                 domTextAreaElement->Release();
418             }
419             domElement->Release();
420         }
421         formDelegate->Release();
422     }
423 }
424
425 class WebEditorUndoCommand : public IWebUndoCommand
426 {
427 public:
428     WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo);
429     void execute();
430
431     // IUnknown
432     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
433     virtual ULONG STDMETHODCALLTYPE AddRef(void);
434     virtual ULONG STDMETHODCALLTYPE Release(void);
435
436 private:
437     ULONG m_refCount;
438     RefPtr<EditCommand> m_editCommand;
439     bool m_isUndo;
440 };
441
442 WebEditorUndoCommand::WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo)
443     : m_editCommand(editCommand)
444     , m_isUndo(isUndo) 
445     , m_refCount(1)
446
447 }
448
449 void WebEditorUndoCommand::execute()
450 {
451     if (m_isUndo)
452         m_editCommand->unapply();
453     else
454         m_editCommand->reapply();
455 }
456
457 HRESULT STDMETHODCALLTYPE WebEditorUndoCommand::QueryInterface(REFIID riid, void** ppvObject)
458 {
459     *ppvObject = 0;
460     if (IsEqualGUID(riid, IID_IUnknown))
461         *ppvObject = static_cast<IWebUndoCommand*>(this);
462     else if (IsEqualGUID(riid, IID_IWebUndoCommand))
463         *ppvObject = static_cast<IWebUndoCommand*>(this);
464     else
465         return E_NOINTERFACE;
466
467     AddRef();
468     return S_OK;
469 }
470
471 ULONG STDMETHODCALLTYPE WebEditorUndoCommand::AddRef(void)
472 {
473     return ++m_refCount;
474 }
475
476 ULONG STDMETHODCALLTYPE WebEditorUndoCommand::Release(void)
477 {
478     ULONG newRef = --m_refCount;
479     if (!newRef)
480         delete(this);
481
482     return newRef;
483 }
484
485 static String undoNameForEditAction(EditAction editAction)
486 {
487     switch (editAction) {
488     case EditActionUnspecified: return String();
489     case EditActionSetColor: return WEB_UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
490     case EditActionSetBackgroundColor: return WEB_UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
491     case EditActionTurnOffKerning: return WEB_UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
492     case EditActionTightenKerning: return WEB_UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
493     case EditActionLoosenKerning: return WEB_UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
494     case EditActionUseStandardKerning: return WEB_UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
495     case EditActionTurnOffLigatures: return WEB_UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
496     case EditActionUseStandardLigatures: return WEB_UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
497     case EditActionUseAllLigatures: return WEB_UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
498     case EditActionRaiseBaseline: return WEB_UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
499     case EditActionLowerBaseline: return WEB_UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
500     case EditActionSetTraditionalCharacterShape: return WEB_UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
501     case EditActionSetFont: return WEB_UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
502     case EditActionChangeAttributes: return WEB_UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
503     case EditActionAlignLeft: return WEB_UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
504     case EditActionAlignRight: return WEB_UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
505     case EditActionCenter: return WEB_UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
506     case EditActionJustify: return WEB_UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
507     case EditActionSetWritingDirection: return WEB_UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
508     case EditActionSubscript: return WEB_UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
509     case EditActionSuperscript: return WEB_UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
510     case EditActionUnderline: return WEB_UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
511     case EditActionOutline: return WEB_UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
512     case EditActionUnscript: return WEB_UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
513     case EditActionDrag: return WEB_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
514     case EditActionCut: return WEB_UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
515     case EditActionPaste: return WEB_UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
516     case EditActionPasteFont: return WEB_UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
517     case EditActionPasteRuler: return WEB_UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
518     case EditActionTyping: return WEB_UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
519     case EditActionCreateLink: return WEB_UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name");
520     case EditActionUnlink: return WEB_UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name");
521     case EditActionInsertList: return WEB_UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name");
522     case EditActionFormatBlock: return WEB_UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name");
523     case EditActionIndent: return WEB_UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name");
524     case EditActionOutdent: return WEB_UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name");
525     }
526     return String();
527 }
528
529 void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
530 {
531     IWebUIDelegate* uiDelegate = 0;
532     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
533         String actionName = undoNameForEditAction(command->editingAction());
534         WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, true);
535         if (!undoCommand)
536             return;
537         uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand);
538         undoCommand->Release(); // the undo manager owns the reference
539         if (!actionName.isEmpty())
540             uiDelegate->setActionTitle(BString(actionName));
541         uiDelegate->Release();
542     }
543 }
544
545 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> command)
546 {
547     IWebUIDelegate* uiDelegate = 0;
548     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
549         WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, false);
550         if (!undoCommand)
551             return;
552         uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand);
553         undoCommand->Release(); // the undo manager owns the reference
554         uiDelegate->Release();
555     }
556 }
557
558 void WebEditorClient::clearUndoRedoOperations()
559 {
560     IWebUIDelegate* uiDelegate = 0;
561     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
562         uiDelegate->removeAllActionsWithTarget(m_undoTarget);
563         uiDelegate->Release();
564     }
565 }
566
567 bool WebEditorClient::canCopyCut(bool defaultValue) const
568 {
569     return defaultValue;
570 }
571
572 bool WebEditorClient::canPaste(bool defaultValue) const
573 {
574     return defaultValue;
575 }
576
577 bool WebEditorClient::canUndo() const
578 {
579     BOOL result = FALSE;
580     IWebUIDelegate* uiDelegate = 0;
581     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
582         uiDelegate->canUndo(&result);
583         uiDelegate->Release();
584     }
585     return !!result;
586 }
587
588 bool WebEditorClient::canRedo() const
589 {
590     BOOL result = FALSE;
591     IWebUIDelegate* uiDelegate = 0;
592     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
593         uiDelegate->canRedo(&result);
594         uiDelegate->Release();
595     }
596     return !!result;
597 }
598
599 void WebEditorClient::undo()
600 {
601     IWebUIDelegate* uiDelegate = 0;
602     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
603         uiDelegate->undo();
604         uiDelegate->Release();
605     }
606 }
607
608 void WebEditorClient::redo()
609 {
610     IWebUIDelegate* uiDelegate = 0;
611     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
612         uiDelegate->redo();
613         uiDelegate->Release();
614     }
615 }
616
617 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* evt)
618 {
619     if (m_webView->handleEditingKeyboardEvent(evt))
620         evt->setDefaultHandled();
621 }
622
623 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* )
624 {
625 }
626
627 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
628 {
629     COMPtr<IWebEditingDelegate> ed;
630     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
631         return;
632
633     initViewSpecificSpelling(m_webView);
634     ed->ignoreWordInSpellDocument(m_webView, BString(word));
635 }
636
637 void WebEditorClient::learnWord(const String& word)
638 {
639     COMPtr<IWebEditingDelegate> ed;
640     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
641         return;
642
643     ed->learnWord(BString(word));
644 }
645
646 void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
647 {
648     *misspellingLocation = -1;
649     *misspellingLength = 0;
650
651     COMPtr<IWebEditingDelegate> ed;
652     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
653         return;
654
655     initViewSpecificSpelling(m_webView);
656     ed->checkSpellingOfString(m_webView, text, length, misspellingLocation, misspellingLength);
657 }
658
659 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord)
660 {
661     // This method can be implemented using customized algorithms for the particular browser.
662     // Currently, it computes an empty string.
663     return String();
664 }
665
666 void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength)
667 {
668     details.clear();
669     *badGrammarLocation = -1;
670     *badGrammarLength = 0;
671
672     COMPtr<IWebEditingDelegate> ed;
673     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
674         return;
675
676     initViewSpecificSpelling(m_webView);
677     COMPtr<IEnumWebGrammarDetails> enumDetailsObj;
678     if (FAILED(ed->checkGrammarOfString(m_webView, text, length, &enumDetailsObj, badGrammarLocation, badGrammarLength)))
679         return;
680
681     while (true) {
682         ULONG fetched;
683         COMPtr<IWebGrammarDetail> detailObj;
684         if (enumDetailsObj->Next(1, &detailObj, &fetched) != S_OK)
685             break;
686
687         GrammarDetail detail;
688         if (FAILED(detailObj->length(&detail.length)))
689             continue;
690         if (FAILED(detailObj->location(&detail.location)))
691             continue;
692         BSTR userDesc;
693         if (FAILED(detailObj->userDescription(&userDesc)))
694             continue;
695         detail.userDescription = String(userDesc, SysStringLen(userDesc));
696         SysFreeString(userDesc);
697
698         COMPtr<IEnumSpellingGuesses> enumGuessesObj;
699         if (FAILED(detailObj->guesses(&enumGuessesObj)))
700             continue;
701         while (true) {
702             BSTR guess;
703             if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
704                 break;
705             detail.guesses.append(String(guess, SysStringLen(guess)));
706             SysFreeString(guess);
707         }
708
709         details.append(detail);
710     }
711 }
712
713 void WebEditorClient::updateSpellingUIWithGrammarString(const String& string, const WebCore::GrammarDetail& detail)
714 {
715     COMPtr<IWebEditingDelegate> ed;
716     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
717         return;
718
719     Vector<BSTR> guessesBSTRs;
720     for (unsigned i = 0; i < detail.guesses.size(); i++) {
721         BString guess(detail.guesses[i]);
722         guessesBSTRs.append(guess.release());
723     }
724     BString userDescriptionBSTR(detail.userDescription);
725     ed->updateSpellingUIWithGrammarString(BString(string), detail.location, detail.length, userDescriptionBSTR, guessesBSTRs.data(), (int)guessesBSTRs.size());
726     for (unsigned i = 0; i < guessesBSTRs.size(); i++)
727         SysFreeString(guessesBSTRs[i]);
728 }
729
730 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& word)
731 {
732     COMPtr<IWebEditingDelegate> ed;
733     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
734         return;
735
736     ed->updateSpellingUIWithMisspelledWord(BString(word));
737 }
738
739 void WebEditorClient::showSpellingUI(bool show)
740 {
741     COMPtr<IWebEditingDelegate> ed;
742     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
743         return;
744     
745     ed->showSpellingUI(show);
746 }
747
748 bool WebEditorClient::spellingUIIsShowing()
749 {
750     COMPtr<IWebEditingDelegate> ed;
751     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
752         return false;
753
754     BOOL showing;
755     if (FAILED(ed->spellingUIIsShowing(&showing)))
756         return false;
757
758     return !!showing;
759 }
760
761 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
762 {
763     guesses.clear();
764
765     COMPtr<IWebEditingDelegate> ed;
766     if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
767         return;
768
769     COMPtr<IEnumSpellingGuesses> enumGuessesObj;
770     if (FAILED(ed->guessesForWord(BString(word), &enumGuessesObj)))
771         return;
772
773     while (true) {
774         ULONG fetched;
775         BSTR guess;
776         if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
777             break;
778         guesses.append(String(guess, SysStringLen(guess)));
779         SysFreeString(guess);
780     }
781 }
782
783 void WebEditorClient::willSetInputMethodState()
784 {
785 }
786
787 void WebEditorClient::setInputMethodState(bool enabled)
788 {
789     m_webView->setInputMethodState(enabled);
790 }