2
* Copyright (C) 2006, 2007 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"
30
#include "IWebEditingDelegate.h"
31
#include "IWebUndoTarget.h"
32
#include "IWebURLResponse.h"
33
#include "WebLocalizableStrings.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>
49
using namespace WebCore;
50
using namespace HTMLNames;
52
// {09A11D2B-FAFB-4ca0-A6F7-791EE8932C88}
53
static const GUID IID_IWebUndoCommand =
54
{ 0x9a11d2b, 0xfafb, 0x4ca0, { 0xa6, 0xf7, 0x79, 0x1e, 0xe8, 0x93, 0x2c, 0x88 } };
56
class IWebUndoCommand : public IUnknown {
58
virtual void execute() = 0;
61
// WebEditorUndoTarget -------------------------------------------------------------
63
class WebEditorUndoTarget : public IWebUndoTarget
66
WebEditorUndoTarget();
69
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
70
virtual ULONG STDMETHODCALLTYPE AddRef(void);
71
virtual ULONG STDMETHODCALLTYPE Release(void);
74
virtual HRESULT STDMETHODCALLTYPE invoke(
75
/* [in] */ BSTR actionName,
76
/* [in] */ IUnknown *obj);
82
WebEditorUndoTarget::WebEditorUndoTarget()
87
HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::QueryInterface(REFIID riid, void** ppvObject)
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);
101
ULONG STDMETHODCALLTYPE WebEditorUndoTarget::AddRef(void)
106
ULONG STDMETHODCALLTYPE WebEditorUndoTarget::Release(void)
108
ULONG newRef = --m_refCount;
115
HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::invoke(
116
/* [in] */ BSTR /*actionName*/,
117
/* [in] */ IUnknown *obj)
119
IWebUndoCommand* undoCommand = 0;
120
if (SUCCEEDED(obj->QueryInterface(IID_IWebUndoCommand, (void**)&undoCommand))) {
121
undoCommand->execute();
122
undoCommand->Release();
127
// WebEditorClient ------------------------------------------------------------------
129
WebEditorClient::WebEditorClient(WebView* webView)
133
m_undoTarget = new WebEditorUndoTarget();
136
WebEditorClient::~WebEditorClient()
139
m_undoTarget->Release();
142
void WebEditorClient::pageDestroyed()
147
bool WebEditorClient::isContinuousSpellCheckingEnabled()
150
if (FAILED(m_webView->isContinuousSpellCheckingEnabled(&enabled)))
155
void WebEditorClient::toggleContinuousSpellChecking()
157
m_webView->toggleContinuousSpellChecking(0);
160
bool WebEditorClient::isGrammarCheckingEnabled()
163
if (FAILED(m_webView->isGrammarCheckingEnabled(&enabled)))
168
void WebEditorClient::toggleGrammarChecking()
170
m_webView->toggleGrammarChecking(0);
173
static void initViewSpecificSpelling(IWebViewEditing* viewEditing)
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.
178
viewEditing->spellCheckerDocumentTag(&tag);
181
int WebEditorClient::spellCheckerDocumentTag()
183
// we don't use the concept of spelling tags
185
ASSERT_NOT_REACHED();
189
bool WebEditorClient::shouldBeginEditing(Range*)
195
bool WebEditorClient::shouldEndEditing(Range*)
201
void WebEditorClient::didBeginEditing()
206
void WebEditorClient::respondToChangedContents()
211
void WebEditorClient::respondToChangedSelection()
213
m_webView->selectionChanged();
216
void WebEditorClient::didEndEditing()
221
void WebEditorClient::didWriteSelectionToPasteboard()
226
void WebEditorClient::didSetSelectionTypesForPasteboard()
231
bool WebEditorClient::shouldDeleteRange(Range* /*range*/)
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();
248
bool WebEditorClient::shouldInsertNode(Node* /*node*/, Range* /*replacingRange*/, EditorInsertAction /*givenAction*/)
254
bool WebEditorClient::shouldInsertText(String /*str*/, Range* /* replacingRange */, EditorInsertAction /*givenAction*/)
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
265
//if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) {
266
// editingDelegate->shouldInsertText(m_webView, text, domRange, (WebViewInsertAction) givenAction, &result);
267
// editingDelegate->Release();
272
//bool WebEditorClient::shouldChangeSelectedRange(Range *currentRange, Range *toProposedRange, SelectionAffinity selectionAffinity, bool stillSelecting)
273
//{ notImplemented(); return false; }
275
bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* /*style*/, Range* /*toElementsInDOMRange*/)
276
{ notImplemented(); return true; }
278
bool WebEditorClient::shouldMoveRangeAfterDelete(Range* /*range*/, Range* /*rangeToBeReplaced*/)
279
{ notImplemented(); return true; }
281
bool WebEditorClient::shouldChangeTypingStyle(CSSStyleDeclaration* /*currentStyle*/, CSSStyleDeclaration* /*toProposedStyle*/)
282
{ notImplemented(); return false; }
284
void WebEditorClient::webViewDidChangeTypingStyle(WebNotification* /*notification*/)
285
{ notImplemented(); }
287
void WebEditorClient::webViewDidChangeSelection(WebNotification* /*notification*/)
288
{ notImplemented(); }
290
bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* /*element*/)
291
{ notImplemented(); return false; }
293
bool WebEditorClient::smartInsertDeleteEnabled(void)
295
BOOL enabled = FALSE;
296
m_webView->smartInsertDeleteEnabled(&enabled);
300
bool WebEditorClient::shouldChangeSelectedRange(WebCore::Range*, WebCore::Range*, WebCore::EAffinity, bool)
301
{ notImplemented(); return true; }
303
void WebEditorClient::textFieldDidBeginEditing(Element* e)
305
IWebFormDelegate* formDelegate;
306
if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
307
IDOMElement* domElement = DOMElement::createInstance(e);
309
IDOMHTMLInputElement* domInputElement;
310
if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
311
formDelegate->textFieldDidBeginEditing(domInputElement, kit(e->document()->frame()));
312
domInputElement->Release();
314
domElement->Release();
316
formDelegate->Release();
320
void WebEditorClient::textFieldDidEndEditing(Element* e)
322
IWebFormDelegate* formDelegate;
323
if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
324
IDOMElement* domElement = DOMElement::createInstance(e);
326
IDOMHTMLInputElement* domInputElement;
327
if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
328
formDelegate->textFieldDidEndEditing(domInputElement, kit(e->document()->frame()));
329
domInputElement->Release();
331
domElement->Release();
333
formDelegate->Release();
337
void WebEditorClient::textDidChangeInTextField(Element* e)
339
IWebFormDelegate* formDelegate;
340
if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
341
IDOMElement* domElement = DOMElement::createInstance(e);
343
IDOMHTMLInputElement* domInputElement;
344
if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
345
formDelegate->textDidChangeInTextField(domInputElement, kit(e->document()->frame()));
346
domInputElement->Release();
348
domElement->Release();
350
formDelegate->Release();
354
bool WebEditorClient::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
357
IWebFormDelegate* formDelegate;
358
if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
359
IDOMElement* domElement = DOMElement::createInstance(e);
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();
369
domElement->Release();
371
formDelegate->Release();
376
void WebEditorClient::textWillBeDeletedInTextField(Element* e)
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);
383
IDOMHTMLInputElement* domInputElement;
384
if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) {
386
formDelegate->doPlatformCommand(domInputElement, BString("BackwardDelete"), kit(e->document()->frame()), &result);
387
domInputElement->Release();
389
domElement->Release();
391
formDelegate->Release();
395
void WebEditorClient::textDidChangeInTextArea(Element* e)
397
IWebFormDelegate* formDelegate;
398
if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) {
399
IDOMElement* domElement = DOMElement::createInstance(e);
401
IDOMHTMLTextAreaElement* domTextAreaElement;
402
if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLTextAreaElement, (void**)&domTextAreaElement))) {
403
formDelegate->textDidChangeInTextArea(domTextAreaElement, kit(e->document()->frame()));
404
domTextAreaElement->Release();
406
domElement->Release();
408
formDelegate->Release();
412
class WebEditorUndoCommand : public IWebUndoCommand
415
WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo);
419
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
420
virtual ULONG STDMETHODCALLTYPE AddRef(void);
421
virtual ULONG STDMETHODCALLTYPE Release(void);
425
RefPtr<EditCommand> m_editCommand;
429
WebEditorUndoCommand::WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo)
430
: m_editCommand(editCommand)
436
void WebEditorUndoCommand::execute()
439
m_editCommand->unapply();
441
m_editCommand->reapply();
444
HRESULT STDMETHODCALLTYPE WebEditorUndoCommand::QueryInterface(REFIID riid, void** ppvObject)
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);
452
return E_NOINTERFACE;
458
ULONG STDMETHODCALLTYPE WebEditorUndoCommand::AddRef(void)
463
ULONG STDMETHODCALLTYPE WebEditorUndoCommand::Release(void)
465
ULONG newRef = --m_refCount;
472
static LPCTSTR undoNameForEditAction(EditAction editAction)
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");
516
void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
518
IWebUIDelegate* uiDelegate = 0;
519
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
520
LPCTSTR actionName = undoNameForEditAction(command->editingAction());
521
WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, true);
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);
531
uiDelegate->Release();
535
void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> command)
537
IWebUIDelegate* uiDelegate = 0;
538
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
539
WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, false);
542
uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand);
543
undoCommand->Release(); // the undo manager owns the reference
544
uiDelegate->Release();
548
void WebEditorClient::clearUndoRedoOperations()
550
IWebUIDelegate* uiDelegate = 0;
551
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
552
uiDelegate->removeAllActionsWithTarget(m_undoTarget);
553
uiDelegate->Release();
557
bool WebEditorClient::canUndo() const
560
IWebUIDelegate* uiDelegate = 0;
561
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
562
uiDelegate->canUndo(&result);
563
uiDelegate->Release();
568
bool WebEditorClient::canRedo() const
571
IWebUIDelegate* uiDelegate = 0;
572
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
573
uiDelegate->canRedo(&result);
574
uiDelegate->Release();
579
void WebEditorClient::undo()
581
IWebUIDelegate* uiDelegate = 0;
582
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
584
uiDelegate->Release();
588
void WebEditorClient::redo()
590
IWebUIDelegate* uiDelegate = 0;
591
if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
593
uiDelegate->Release();
597
void WebEditorClient::handleKeypress(KeyboardEvent* evt)
599
if (m_webView->handleEditingKeyboardEvent(evt))
600
evt->setDefaultHandled();
603
void WebEditorClient::handleInputMethodKeypress(KeyboardEvent* evt)
605
if (m_webView->inIMEKeyDown())
606
evt->setDefaultHandled();
609
bool WebEditorClient::isEditable()
614
void WebEditorClient::ignoreWordInSpellDocument(const String& word)
616
COMPtr<IWebEditingDelegate> ed;
617
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
620
initViewSpecificSpelling(m_webView);
621
ed->ignoreWordInSpellDocument(m_webView, BString(word));
624
void WebEditorClient::learnWord(const String& word)
626
COMPtr<IWebEditingDelegate> ed;
627
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
630
ed->learnWord(BString(word));
633
void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
635
*misspellingLocation = -1;
636
*misspellingLength = 0;
638
COMPtr<IWebEditingDelegate> ed;
639
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
642
initViewSpecificSpelling(m_webView);
643
ed->checkSpellingOfString(m_webView, text, length, misspellingLocation, misspellingLength);
646
void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength)
649
*badGrammarLocation = -1;
650
*badGrammarLength = 0;
652
COMPtr<IWebEditingDelegate> ed;
653
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
656
initViewSpecificSpelling(m_webView);
657
COMPtr<IEnumWebGrammarDetails> enumDetailsObj;
658
if (FAILED(ed->checkGrammarOfString(m_webView, text, length, &enumDetailsObj, badGrammarLocation, badGrammarLength)))
663
COMPtr<IWebGrammarDetail> detailObj;
664
if (enumDetailsObj->Next(1, &detailObj, &fetched) != S_OK)
667
GrammarDetail detail;
668
if (FAILED(detailObj->length(&detail.length)))
670
if (FAILED(detailObj->location(&detail.location)))
673
if (FAILED(detailObj->userDescription(&userDesc)))
675
detail.userDescription = String(userDesc, SysStringLen(userDesc));
676
SysFreeString(userDesc);
678
COMPtr<IEnumSpellingGuesses> enumGuessesObj;
679
if (FAILED(detailObj->guesses(&enumGuessesObj)))
683
if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
685
detail.guesses.append(String(guess, SysStringLen(guess)));
686
SysFreeString(guess);
689
details.append(detail);
693
void WebEditorClient::updateSpellingUIWithGrammarString(const String& string, const WebCore::GrammarDetail& detail)
695
COMPtr<IWebEditingDelegate> ed;
696
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
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());
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]);
710
void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& word)
712
COMPtr<IWebEditingDelegate> ed;
713
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
716
ed->updateSpellingUIWithMisspelledWord(BString(word));
719
void WebEditorClient::showSpellingUI(bool show)
721
COMPtr<IWebEditingDelegate> ed;
722
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
725
ed->showSpellingUI(show);
728
bool WebEditorClient::spellingUIIsShowing()
730
COMPtr<IWebEditingDelegate> ed;
731
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
735
if (FAILED(ed->spellingUIIsShowing(&showing)))
741
void WebEditorClient::getGuessesForWord(const String& word, Vector<String>& guesses)
745
COMPtr<IWebEditingDelegate> ed;
746
if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get())
749
COMPtr<IEnumSpellingGuesses> enumGuessesObj;
750
if (FAILED(ed->guessesForWord(BString(word), &enumGuessesObj)))
756
if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK)
758
guesses.append(String(guess, SysStringLen(guess)));
759
SysFreeString(guess);