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