2 * Copyright (C) 2006, 2007, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebKitDLL.h"
28 #include "WebEditorClient.h"
31 #include "WebNotification.h"
32 #include "WebNotificationCenter.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>
48 using namespace WebCore;
49 using namespace HTMLNames;
51 // {09A11D2B-FAFB-4ca0-A6F7-791EE8932C88}
52 static const GUID IID_IWebUndoCommand =
53 { 0x9a11d2b, 0xfafb, 0x4ca0, { 0xa6, 0xf7, 0x79, 0x1e, 0xe8, 0x93, 0x2c, 0x88 } };
55 class IWebUndoCommand : public IUnknown {
57 virtual void execute() = 0;
60 // WebEditorUndoTarget -------------------------------------------------------------
62 class WebEditorUndoTarget : public IWebUndoTarget
65 WebEditorUndoTarget();
68 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
69 virtual ULONG STDMETHODCALLTYPE AddRef(void);
70 virtual ULONG STDMETHODCALLTYPE Release(void);
73 virtual HRESULT STDMETHODCALLTYPE invoke(
74 /* [in] */ BSTR actionName,
75 /* [in] */ IUnknown *obj);
81 WebEditorUndoTarget::WebEditorUndoTarget()
86 HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::QueryInterface(REFIID riid, void** ppvObject)
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);
100 ULONG STDMETHODCALLTYPE WebEditorUndoTarget::AddRef(void)
105 ULONG STDMETHODCALLTYPE WebEditorUndoTarget::Release(void)
107 ULONG newRef = --m_refCount;
114 HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::invoke(
115 /* [in] */ BSTR /*actionName*/,
116 /* [in] */ IUnknown *obj)
118 IWebUndoCommand* undoCommand = 0;
119 if (SUCCEEDED(obj->QueryInterface(IID_IWebUndoCommand, (void**)&undoCommand))) {
120 undoCommand->execute();
121 undoCommand->Release();
126 // WebEditorClient ------------------------------------------------------------------
128 WebEditorClient::WebEditorClient(WebView* webView)
132 m_undoTarget = new WebEditorUndoTarget();
135 WebEditorClient::~WebEditorClient()
138 m_undoTarget->Release();
141 void WebEditorClient::pageDestroyed()
146 bool WebEditorClient::isContinuousSpellCheckingEnabled()
149 if (FAILED(m_webView->isContinuousSpellCheckingEnabled(&enabled)))
154 void WebEditorClient::toggleContinuousSpellChecking()
156 m_webView->toggleContinuousSpellChecking(0);
159 bool WebEditorClient::isGrammarCheckingEnabled()
162 if (FAILED(m_webView->isGrammarCheckingEnabled(&enabled)))
167 void WebEditorClient::toggleGrammarChecking()
169 m_webView->toggleGrammarChecking(0);
172 static void initViewSpecificSpelling(IWebViewEditing* viewEditing)
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.
177 viewEditing->spellCheckerDocumentTag(&tag);
180 int WebEditorClient::spellCheckerDocumentTag()
182 // we don't use the concept of spelling tags
184 ASSERT_NOT_REACHED();
188 bool WebEditorClient::shouldBeginEditing(Range*)
194 bool WebEditorClient::shouldEndEditing(Range*)
200 void WebEditorClient::didBeginEditing()
205 void WebEditorClient::respondToChangedContents()
210 void WebEditorClient::respondToChangedSelection()
212 m_webView->selectionChanged();
214 static BSTR webViewDidChangeSelectionNotificationName = SysAllocString(WebViewDidChangeSelectionNotification);
215 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
216 notifyCenter->postNotificationName(webViewDidChangeSelectionNotificationName, static_cast<IWebView*>(m_webView), 0);
219 void WebEditorClient::didEndEditing()
224 void WebEditorClient::didWriteSelectionToPasteboard()
229 void WebEditorClient::didSetSelectionTypesForPasteboard()
234 bool WebEditorClient::shouldDeleteRange(Range* /*range*/)
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();
251 bool WebEditorClient::shouldInsertNode(Node* /*node*/, Range* /*replacingRange*/, EditorInsertAction /*givenAction*/)
257 bool WebEditorClient::shouldInsertText(const String& /*str*/, Range* /* replacingRange */, EditorInsertAction /*givenAction*/)
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
268 //if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) {
269 // editingDelegate->shouldInsertText(m_webView, text, domRange, (WebViewInsertAction) givenAction, &result);
270 // editingDelegate->Release();
275 //bool WebEditorClient::shouldChangeSelectedRange(Range *currentRange, Range *toProposedRange, SelectionAffinity selectionAffinity, bool stillSelecting)
276 //{ notImplemented(); return false; }
278 bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* /*style*/, Range* /*toElementsInDOMRange*/)
279 { notImplemented(); return true; }
281 bool WebEditorClient::shouldMoveRangeAfterDelete(Range* /*range*/, Range* /*rangeToBeReplaced*/)
282 { notImplemented(); return true; }
284 bool WebEditorClient::shouldChangeTypingStyle(CSSStyleDeclaration* /*currentStyle*/, CSSStyleDeclaration* /*toProposedStyle*/)
285 { notImplemented(); return false; }
287 void WebEditorClient::webViewDidChangeTypingStyle(WebNotification* /*notification*/)
288 { notImplemented(); }
290 void WebEditorClient::webViewDidChangeSelection(WebNotification* /*notification*/)
291 { notImplemented(); }
293 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* /*element*/)
294 { notImplemented(); return false; }
296 bool WebEditorClient::smartInsertDeleteEnabled(void)
298 BOOL enabled = FALSE;
299 m_webView->smartInsertDeleteEnabled(&enabled);
303 bool WebEditorClient::isSelectTrailingWhitespaceEnabled(void)
305 BOOL enabled = FALSE;
306 m_webView->isSelectTrailingWhitespaceEnabled(&enabled);
310 bool WebEditorClient::shouldChangeSelectedRange(WebCore::Range*, WebCore::Range*, WebCore::EAffinity, bool)
311 { notImplemented(); return true; }
313 void WebEditorClient::textFieldDidBeginEditing(Element* e)
315 IWebFormDelegate* formDelegate;
316 if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
317 IDOMElement* domElement = DOMElement::createInstance(e);
319 IDOMHTMLInputElement* domInputElement;
320 if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
321 formDelegate->textFieldDidBeginEditing(domInputElement, kit(e->document()->frame()));
322 domInputElement->Release();
324 domElement->Release();
326 formDelegate->Release();
330 void WebEditorClient::textFieldDidEndEditing(Element* e)
332 IWebFormDelegate* formDelegate;
333 if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
334 IDOMElement* domElement = DOMElement::createInstance(e);
336 IDOMHTMLInputElement* domInputElement;
337 if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
338 formDelegate->textFieldDidEndEditing(domInputElement, kit(e->document()->frame()));
339 domInputElement->Release();
341 domElement->Release();
343 formDelegate->Release();
347 void WebEditorClient::textDidChangeInTextField(Element* e)
349 if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != e)
352 IWebFormDelegate* formDelegate;
353 if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
354 IDOMElement* domElement = DOMElement::createInstance(e);
356 IDOMHTMLInputElement* domInputElement;
357 if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
358 formDelegate->textDidChangeInTextField(domInputElement, kit(e->document()->frame()));
359 domInputElement->Release();
361 domElement->Release();
363 formDelegate->Release();
367 bool WebEditorClient::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
370 IWebFormDelegate* formDelegate;
371 if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
372 IDOMElement* domElement = DOMElement::createInstance(e);
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();
382 domElement->Release();
384 formDelegate->Release();
389 void WebEditorClient::textWillBeDeletedInTextField(Element* e)
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);
396 IDOMHTMLInputElement* domInputElement;
397 if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
399 formDelegate->doPlatformCommand(domInputElement, BString(L"DeleteBackward"), kit(e->document()->frame()), &result);
400 domInputElement->Release();
402 domElement->Release();
404 formDelegate->Release();
408 void WebEditorClient::textDidChangeInTextArea(Element* e)
410 IWebFormDelegate* formDelegate;
411 if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
412 IDOMElement* domElement = DOMElement::createInstance(e);
414 IDOMHTMLTextAreaElement* domTextAreaElement;
415 if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLTextAreaElement, (void**)&domTextAreaElement))) {
416 formDelegate->textDidChangeInTextArea(domTextAreaElement, kit(e->document()->frame()));
417 domTextAreaElement->Release();
419 domElement->Release();
421 formDelegate->Release();
425 class WebEditorUndoCommand : public IWebUndoCommand
428 WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo);
432 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
433 virtual ULONG STDMETHODCALLTYPE AddRef(void);
434 virtual ULONG STDMETHODCALLTYPE Release(void);
438 RefPtr<EditCommand> m_editCommand;
442 WebEditorUndoCommand::WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo)
443 : m_editCommand(editCommand)
449 void WebEditorUndoCommand::execute()
452 m_editCommand->unapply();
454 m_editCommand->reapply();
457 HRESULT STDMETHODCALLTYPE WebEditorUndoCommand::QueryInterface(REFIID riid, void** ppvObject)
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);
465 return E_NOINTERFACE;
471 ULONG STDMETHODCALLTYPE WebEditorUndoCommand::AddRef(void)
476 ULONG STDMETHODCALLTYPE WebEditorUndoCommand::Release(void)
478 ULONG newRef = --m_refCount;
485 static String undoNameForEditAction(EditAction editAction)
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");
529 void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
531 IWebUIDelegate* uiDelegate = 0;
532 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
533 String actionName = undoNameForEditAction(command->editingAction());
534 WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, true);
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();
545 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> command)
547 IWebUIDelegate* uiDelegate = 0;
548 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
549 WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, false);
552 uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand);
553 undoCommand->Release(); // the undo manager owns the reference
554 uiDelegate->Release();
558 void WebEditorClient::clearUndoRedoOperations()
560 IWebUIDelegate* uiDelegate = 0;
561 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
562 uiDelegate->removeAllActionsWithTarget(m_undoTarget);
563 uiDelegate->Release();
567 bool WebEditorClient::canCopyCut(bool defaultValue) const
572 bool WebEditorClient::canPaste(bool defaultValue) const
577 bool WebEditorClient::canUndo() const
580 IWebUIDelegate* uiDelegate = 0;
581 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
582 uiDelegate->canUndo(&result);
583 uiDelegate->Release();
588 bool WebEditorClient::canRedo() const
591 IWebUIDelegate* uiDelegate = 0;
592 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
593 uiDelegate->canRedo(&result);
594 uiDelegate->Release();
599 void WebEditorClient::undo()
601 IWebUIDelegate* uiDelegate = 0;
602 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
604 uiDelegate->Release();
608 void WebEditorClient::redo()
610 IWebUIDelegate* uiDelegate = 0;
611 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
613 uiDelegate->Release();
617 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* evt)
619 if (m_webView->handleEditingKeyboardEvent(evt))
620 evt->setDefaultHandled();
623 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* )
627 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
629 COMPtr<IWebEditingDelegate> ed;
630 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
633 initViewSpecificSpelling(m_webView);
634 ed->ignoreWordInSpellDocument(m_webView, BString(word));
637 void WebEditorClient::learnWord(const String& word)
639 COMPtr<IWebEditingDelegate> ed;
640 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
643 ed->learnWord(BString(word));
646 void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
648 *misspellingLocation = -1;
649 *misspellingLength = 0;
651 COMPtr<IWebEditingDelegate> ed;
652 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
655 initViewSpecificSpelling(m_webView);
656 ed->checkSpellingOfString(m_webView, text, length, misspellingLocation, misspellingLength);
659 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord)
661 // This method can be implemented using customized algorithms for the particular browser.
662 // Currently, it computes an empty string.
666 void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength)
669 *badGrammarLocation = -1;
670 *badGrammarLength = 0;
672 COMPtr<IWebEditingDelegate> ed;
673 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
676 initViewSpecificSpelling(m_webView);
677 COMPtr<IEnumWebGrammarDetails> enumDetailsObj;
678 if (FAILED(ed->checkGrammarOfString(m_webView, text, length, &enumDetailsObj, badGrammarLocation, badGrammarLength)))
683 COMPtr<IWebGrammarDetail> detailObj;
684 if (enumDetailsObj->Next(1, &detailObj, &fetched) != S_OK)
687 GrammarDetail detail;
688 if (FAILED(detailObj->length(&detail.length)))
690 if (FAILED(detailObj->location(&detail.location)))
693 if (FAILED(detailObj->userDescription(&userDesc)))
695 detail.userDescription = String(userDesc, SysStringLen(userDesc));
696 SysFreeString(userDesc);
698 COMPtr<IEnumSpellingGuesses> enumGuessesObj;
699 if (FAILED(detailObj->guesses(&enumGuessesObj)))
703 if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
705 detail.guesses.append(String(guess, SysStringLen(guess)));
706 SysFreeString(guess);
709 details.append(detail);
713 void WebEditorClient::updateSpellingUIWithGrammarString(const String& string, const WebCore::GrammarDetail& detail)
715 COMPtr<IWebEditingDelegate> ed;
716 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
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());
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]);
730 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& word)
732 COMPtr<IWebEditingDelegate> ed;
733 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
736 ed->updateSpellingUIWithMisspelledWord(BString(word));
739 void WebEditorClient::showSpellingUI(bool show)
741 COMPtr<IWebEditingDelegate> ed;
742 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
745 ed->showSpellingUI(show);
748 bool WebEditorClient::spellingUIIsShowing()
750 COMPtr<IWebEditingDelegate> ed;
751 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
755 if (FAILED(ed->spellingUIIsShowing(&showing)))
761 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
765 COMPtr<IWebEditingDelegate> ed;
766 if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
769 COMPtr<IEnumSpellingGuesses> enumGuessesObj;
770 if (FAILED(ed->guessesForWord(BString(word), &enumGuessesObj)))
776 if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
778 guesses.append(String(guess, SysStringLen(guess)));
779 SysFreeString(guess);
783 void WebEditorClient::willSetInputMethodState()
787 void WebEditorClient::setInputMethodState(bool enabled)
789 m_webView->setInputMethodState(enabled);