WebEditorClient.mm 19.7 KB
Newer Older
aliceli1's avatar
aliceli1 committed
1
2
/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
mjs's avatar
mjs committed
3
 * Copyright (C) 2007 Trolltech ASA
aliceli1's avatar
aliceli1 committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "WebEditorClient.h"

mjs's avatar
mjs committed
32
33
34
#import "DOMHTMLInputElementInternal.h"
#import "DOMHTMLTextAreaElementInternal.h"
#import "DOMRangeInternal.h"
adele's avatar
adele committed
35
36
#import "WebArchive.h"
#import "WebArchiver.h"
aliceli1's avatar
aliceli1 committed
37
#import "WebDataSourceInternal.h"
andersca's avatar
andersca committed
38
#import "WebDocument.h"
adele's avatar
adele committed
39
#import "WebEditingDelegatePrivate.h"
mjs's avatar
mjs committed
40
#import "WebFormDelegate.h"
darin's avatar
darin committed
41
#import "WebFrameInternal.h"
andersca's avatar
andersca committed
42
43
#import "WebHTMLView.h"
#import "WebHTMLViewInternal.h"
mjs's avatar
mjs committed
44
#import "WebKitLogging.h"
harrison's avatar
harrison committed
45
46
#import "WebKitVersionChecks.h"
#import "WebLocalizableStrings.h"
aliceli1's avatar
aliceli1 committed
47
#import "WebNSURLExtras.h"
adele's avatar
adele committed
48
49
#import "WebViewInternal.h"
#import <WebCore/Document.h>
andersca's avatar
andersca committed
50
51
#import <WebCore/EditAction.h>
#import <WebCore/EditCommand.h>
adele's avatar
adele committed
52
53
#import <WebCore/KeyboardEvent.h>
#import <WebCore/PlatformKeyboardEvent.h>
adele's avatar
adele committed
54
#import <WebCore/PlatformString.h>
thatcher's avatar
thatcher committed
55
#import <WebCore/WebCoreObjCExtras.h>
adele's avatar
adele committed
56
#import <wtf/PassRefPtr.h>
aliceli1's avatar
aliceli1 committed
57

andersca's avatar
andersca committed
58
59
using namespace WebCore;

bdakin's avatar
bdakin committed
60
61
62
63
64
65
66
67
68
69
70
71
72
EditorInsertAction core(WebViewInsertAction);
WebViewInsertAction kit(EditorInsertAction);

EditorInsertAction core(WebViewInsertAction kitAction)
{
    return static_cast<EditorInsertAction>(kitAction);
}

WebViewInsertAction kit(EditorInsertAction coreAction)
{
    return static_cast<WebViewInsertAction>(coreAction);
}

andersca's avatar
andersca committed
73
74
75
76
77
78
79
80
81
82
83
84
@interface WebEditCommand : NSObject
{
    EditCommand *m_command;   
}

+ (WebEditCommand *)commandWithEditCommand:(PassRefPtr<EditCommand>)command;
- (EditCommand *)command;

@end

@implementation WebEditCommand

thatcher's avatar
thatcher committed
85
86
87
88
89
90
91
#ifndef BUILDING_ON_TIGER
+ (void)initialize
{
    WebCoreObjCFinalizeOnMainThread(self);
}
#endif

andersca's avatar
andersca committed
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
- (id)initWithEditCommand:(PassRefPtr<WebCore::EditCommand>)command
{
    ASSERT(command);
    [super init];
    m_command = command.releaseRef();
    return self;
}

- (void)dealloc
{
    m_command->deref();
    [super dealloc];
}

- (void)finalize
{
thatcher's avatar
thatcher committed
108
    ASSERT_MAIN_THREAD();
andersca's avatar
andersca committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    m_command->deref();
    [super finalize];
}

+ (WebEditCommand *)commandWithEditCommand:(PassRefPtr<EditCommand>)command
{
    return [[[WebEditCommand alloc] initWithEditCommand:command] autorelease];
}

- (EditCommand *)command;
{
    return m_command;
}

@end

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@interface WebEditorUndoTarget : NSObject
{
}

- (void)undoEditing:(id)arg;
- (void)redoEditing:(id)arg;

@end

@implementation WebEditorUndoTarget

- (void)undoEditing:(id)arg
{
    ASSERT([arg isKindOfClass:[WebEditCommand class]]);
    [arg command]->unapply();
}

- (void)redoEditing:(id)arg
{
    ASSERT([arg isKindOfClass:[WebEditCommand class]]);
    [arg command]->reapply();
}

@end

ggaren's avatar
ggaren committed
150
void WebEditorClient::pageDestroyed()
ggaren's avatar
ggaren committed
151
{
ggaren's avatar
ggaren committed
152
    delete this;
ggaren's avatar
ggaren committed
153
154
}

ggaren's avatar
ggaren committed
155
156
WebEditorClient::WebEditorClient(WebView *webView)
    : m_webView(webView)
andersca's avatar
andersca committed
157
158
159
160
161
    , m_undoTarget([[[WebEditorUndoTarget alloc] init] autorelease])
    , m_haveUndoRedoOperations(false)
{
}

sullivan's avatar
sullivan committed
162
163
bool WebEditorClient::isContinuousSpellCheckingEnabled()
{
ggaren's avatar
ggaren committed
164
    return [m_webView isContinuousSpellCheckingEnabled];
sullivan's avatar
sullivan committed
165
166
}

bdakin's avatar
bdakin committed
167
168
169
170
171
void WebEditorClient::toggleContinuousSpellChecking()
{
    [m_webView toggleContinuousSpellChecking:nil];
}

sullivan's avatar
sullivan committed
172
173
174
175
176
bool WebEditorClient::isGrammarCheckingEnabled()
{
#ifdef BUILDING_ON_TIGER
    return false;
#else
ggaren's avatar
ggaren committed
177
    return [m_webView isGrammarCheckingEnabled];
sullivan's avatar
sullivan committed
178
179
180
#endif
}

bdakin's avatar
bdakin committed
181
182
183
184
185
186
187
void WebEditorClient::toggleGrammarChecking()
{
#ifndef BUILDING_ON_TIGER
    [m_webView toggleGrammarChecking:nil];
#endif
}

sullivan's avatar
sullivan committed
188
189
int WebEditorClient::spellCheckerDocumentTag()
{
ggaren's avatar
ggaren committed
190
    return [m_webView spellCheckerDocumentTag];
sullivan's avatar
sullivan committed
191
192
}

bdakin's avatar
bdakin committed
193
194
bool WebEditorClient::selectWordBeforeMenuEvent()
{
ggaren's avatar
ggaren committed
195
    return [m_webView _selectWordBeforeMenuEvent];
bdakin's avatar
bdakin committed
196
197
198
199
}

bool WebEditorClient::isEditable()
{
ggaren's avatar
ggaren committed
200
    return [m_webView isEditable];
bdakin's avatar
bdakin committed
201
202
}

andersca's avatar
andersca committed
203
bool WebEditorClient::shouldDeleteRange(Range* range)
aliceli1's avatar
aliceli1 committed
204
{
ggaren's avatar
ggaren committed
205
    return [[m_webView _editingDelegateForwarder] webView:m_webView
darin's avatar
darin committed
206
        shouldDeleteDOMRange:kit(range)];
aliceli1's avatar
aliceli1 committed
207
208
}

andersca's avatar
andersca committed
209
bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* element)
thatcher's avatar
thatcher committed
210
{
ggaren's avatar
ggaren committed
211
    return [[m_webView _editingDelegateForwarder] webView:m_webView
darin's avatar
darin committed
212
        shouldShowDeleteInterfaceForElement:kit(element)];
thatcher's avatar
thatcher committed
213
214
}

aliceli1's avatar
aliceli1 committed
215
216
217
218
219
bool WebEditorClient::smartInsertDeleteEnabled()
{
    return [m_webView smartInsertDeleteEnabled];
}

andersca's avatar
andersca committed
220
221
bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range)
{
ggaren's avatar
ggaren committed
222
    return [[m_webView _editingDelegateForwarder] webView:m_webView
andersca's avatar
andersca committed
223
224
225
        shouldApplyStyle:kit(style) toElementsInDOMRange:kit(range)];
}

andersca's avatar
andersca committed
226
227
bool WebEditorClient::shouldBeginEditing(Range* range)
{
ggaren's avatar
ggaren committed
228
    return [[m_webView _editingDelegateForwarder] webView:m_webView
andersca's avatar
andersca committed
229
230
231
232
233
234
235
        shouldBeginEditingInDOMRange:kit(range)];

    return false;
}

bool WebEditorClient::shouldEndEditing(Range* range)
{
ggaren's avatar
ggaren committed
236
    return [[m_webView _editingDelegateForwarder] webView:m_webView
andersca's avatar
andersca committed
237
238
239
                             shouldEndEditingInDOMRange:kit(range)];
}

bdakin's avatar
bdakin committed
240
241
bool WebEditorClient::shouldInsertText(String text, Range* range, EditorInsertAction action)
{
ggaren's avatar
ggaren committed
242
    WebView* webView = m_webView;
bdakin's avatar
bdakin committed
243
244
245
    return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:text replacingDOMRange:kit(range) givenAction:kit(action)];
}

mjs's avatar
mjs committed
246
247
248
249
250
bool WebEditorClient::shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity selectionAffinity, bool stillSelecting)
{
    return [m_webView _shouldChangeSelectedDOMRange:kit(fromRange) toDOMRange:kit(toRange) affinity:kit(selectionAffinity) stillSelecting:stillSelecting];
}

andersca's avatar
andersca committed
251
252
void WebEditorClient::didBeginEditing()
{
ggaren's avatar
ggaren committed
253
    [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidBeginEditingNotification object:m_webView];
andersca's avatar
andersca committed
254
255
256
257
}

void WebEditorClient::respondToChangedContents()
{
ggaren's avatar
ggaren committed
258
    NSView <WebDocumentView> *view = [[[m_webView selectedFrame] frameView] documentView];
andersca's avatar
andersca committed
259
260
    if ([view isKindOfClass:[WebHTMLView class]])
        [(WebHTMLView *)view _updateFontPanel];
ggaren's avatar
ggaren committed
261
    [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:m_webView];    
andersca's avatar
andersca committed
262
263
}

264
265
266
267
268
void WebEditorClient::respondToChangedSelection()
{
    NSView <WebDocumentView> *view = [[[m_webView selectedFrame] frameView] documentView];
    if ([view isKindOfClass:[WebHTMLView class]])
        [(WebHTMLView *)view _selectionChanged];
harrison's avatar
harrison committed
269
270
271
272
273

    // FIXME: This quirk is needed due to <rdar://problem/5009625> - We can phase it out once Aperture can adopt the new behavior on their end
    if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
        return;

274
275
276
    [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:m_webView];
}

andersca's avatar
andersca committed
277
278
void WebEditorClient::didEndEditing()
{
ggaren's avatar
ggaren committed
279
    [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidEndEditingNotification object:m_webView];
andersca's avatar
andersca committed
280
281
}

aliceli1's avatar
aliceli1 committed
282
283
284
285
286
void WebEditorClient::didWriteSelectionToPasteboard()
{
    [[m_webView _editingDelegateForwarder] webView:m_webView didWriteSelectionToPasteboard:[NSPasteboard generalPasteboard]];
}

aliceli1's avatar
aliceli1 committed
287
288
289
290
291
void WebEditorClient::didSetSelectionTypesForPasteboard()
{
    [[m_webView _editingDelegateForwarder] webView:m_webView didSetSelectionTypesForPasteboard:[NSPasteboard generalPasteboard]];
}

aliceli1's avatar
aliceli1 committed
292
NSData* WebEditorClient::dataForArchivedSelection(Frame* frame)
aliceli1's avatar
aliceli1 committed
293
{
aliceli1's avatar
aliceli1 committed
294
    WebArchive *archive = [WebArchiver archiveSelectionInFrame:kit(frame)];
aliceli1's avatar
aliceli1 committed
295
296
297
    return [archive data];
}

darin's avatar
darin committed
298
NSString* WebEditorClient::userVisibleString(NSURL *URL)
aliceli1's avatar
aliceli1 committed
299
300
301
302
{
    return [URL _web_userVisibleString];
}

aliceli1's avatar
aliceli1 committed
303
304
305
306
307
308
309
310
#ifdef BUILDING_ON_TIGER
NSArray* WebEditorClient::pasteboardTypesForSelection(Frame* selectedFrame)
{
    WebFrame* frame = kit(selectedFrame);
    return [[[frame frameView] documentView] pasteboardTypesForSelection];
}
#endif

aliceli1's avatar
aliceli1 committed
311
312
313
314
315
bool WebEditorClient::shouldInsertNode(Node *node, Range* replacingRange, EditorInsertAction givenAction)
{ 
    return [[m_webView _editingDelegateForwarder] webView:m_webView shouldInsertNode:kit(node) replacingDOMRange:kit(replacingRange) givenAction:(WebViewInsertAction)givenAction];
}

andersca's avatar
andersca committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
static NSString* undoNameForEditAction(EditAction editAction)
{
    switch (editAction) {
        case EditActionUnspecified: return nil;
        case EditActionSetColor: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
        case EditActionSetBackgroundColor: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
        case EditActionTurnOffKerning: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
        case EditActionTightenKerning: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
        case EditActionLoosenKerning: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
        case EditActionUseStandardKerning: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
        case EditActionTurnOffLigatures: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
        case EditActionUseStandardLigatures: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
        case EditActionUseAllLigatures: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
        case EditActionRaiseBaseline: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
        case EditActionLowerBaseline: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
        case EditActionSetTraditionalCharacterShape: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
        case EditActionSetFont: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
        case EditActionChangeAttributes: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
        case EditActionAlignLeft: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
        case EditActionAlignRight: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
        case EditActionCenter: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
        case EditActionJustify: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
        case EditActionSetWritingDirection: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
        case EditActionSubscript: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
        case EditActionSuperscript: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
        case EditActionUnderline: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
        case EditActionOutline: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
        case EditActionUnscript: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
        case EditActionDrag: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
        case EditActionCut: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
        case EditActionPaste: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
        case EditActionPasteFont: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
        case EditActionPasteRuler: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
        case EditActionTyping: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
        case EditActionCreateLink: return UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name");
        case EditActionUnlink: return UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name");
        case EditActionInsertList: return UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name");
        case EditActionFormatBlock: return UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name");
        case EditActionIndent: return UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name");
        case EditActionOutdent: return UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name");
    }
    return nil;
}

void WebEditorClient::registerCommandForUndoOrRedo(PassRefPtr<EditCommand> cmd, bool isRedo)
{
    ASSERT(cmd);
    
ggaren's avatar
ggaren committed
364
    NSUndoManager *undoManager = [m_webView undoManager];
andersca's avatar
andersca committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    NSString *actionName = undoNameForEditAction(cmd->editingAction());
    WebEditCommand *command = [WebEditCommand commandWithEditCommand:cmd];
    [undoManager registerUndoWithTarget:m_undoTarget.get() selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:command];
    if (actionName)
        [undoManager setActionName:actionName];
    m_haveUndoRedoOperations = YES;
}

void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> cmd)
{
    registerCommandForUndoOrRedo(cmd, false);
}

void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> cmd)
{
    registerCommandForUndoOrRedo(cmd, true);
}

void WebEditorClient::clearUndoRedoOperations()
{
    if (m_haveUndoRedoOperations) {
        // workaround for <rdar://problem/4645507> NSUndoManager dies
        // with uncaught exception when undo items cleared while
        // groups are open
ggaren's avatar
ggaren committed
389
        NSUndoManager *undoManager = [m_webView undoManager];
andersca's avatar
andersca committed
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
        int groupingLevel = [undoManager groupingLevel];
        for (int i = 0; i < groupingLevel; ++i)
            [undoManager endUndoGrouping];
        
        [undoManager removeAllActionsWithTarget:m_undoTarget.get()];
        
        for (int i = 0; i < groupingLevel; ++i)
            [undoManager beginUndoGrouping];
        
        m_haveUndoRedoOperations = NO;
    }    
}

bool WebEditorClient::canUndo() const
{
ggaren's avatar
ggaren committed
405
    return [[m_webView undoManager] canUndo];
andersca's avatar
andersca committed
406
407
408
409
}

bool WebEditorClient::canRedo() const
{
ggaren's avatar
ggaren committed
410
    return [[m_webView undoManager] canRedo];
andersca's avatar
andersca committed
411
412
413
414
415
}

void WebEditorClient::undo()
{
    if (canUndo())
ggaren's avatar
ggaren committed
416
        [[m_webView undoManager] undo];
andersca's avatar
andersca committed
417
418
419
420
421
}

void WebEditorClient::redo()
{
    if (canRedo())
ggaren's avatar
ggaren committed
422
        [[m_webView undoManager] redo];    
andersca's avatar
andersca committed
423
424
}

adele's avatar
adele committed
425
void WebEditorClient::handleKeypress(KeyboardEvent* event)
adele's avatar
adele committed
426
{
adele's avatar
adele committed
427
428
    Frame* frame = event->target()->toNode()->document()->frame();
    WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView];
adele's avatar
adele committed
429
430
431
432
433
434
435
436
437
    if ([webHTMLView _interceptEditingKeyEvent:event shouldSaveCommand:NO])
        event->setDefaultHandled();
}

void WebEditorClient::handleInputMethodKeypress(KeyboardEvent* event)
{
    Frame* frame = event->target()->toNode()->document()->frame();
    WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView];
    if ([webHTMLView _interceptEditingKeyEvent:event shouldSaveCommand:YES])
adele's avatar
adele committed
438
        event->setDefaultHandled();
adele's avatar
adele committed
439
440
}

darin's avatar
darin committed
441
442
443
444
445
void WebEditorClient::markedTextAbandoned(Frame* frame)
{
    WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView];
    [[NSInputManager currentInputManager] markedTextAbandoned:webHTMLView];
}
mjs's avatar
mjs committed
446
447
448
449
450

#define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)

void WebEditorClient::textFieldDidBeginEditing(WebCore::Element* element)
{
darin's avatar
darin committed
451
    DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(WebCore::HTMLInputElement*)element];
mjs's avatar
mjs committed
452
453
454
455
456
457
    FormDelegateLog(inputElement);
    [[m_webView _formDelegate] textFieldDidBeginEditing:inputElement inFrame:kit(element->document()->frame())];
}

void WebEditorClient::textFieldDidEndEditing(WebCore::Element* element)
{
darin's avatar
darin committed
458
    DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(WebCore::HTMLInputElement*)element];
mjs's avatar
mjs committed
459
460
461
462
463
464
    FormDelegateLog(inputElement);
    [[m_webView _formDelegate] textFieldDidEndEditing:inputElement inFrame:kit(element->document()->frame())];
}
    
void WebEditorClient::textDidChangeInTextField(WebCore::Element* element)
{
darin's avatar
darin committed
465
    DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(WebCore::HTMLInputElement*)element];
mjs's avatar
mjs committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
    FormDelegateLog(inputElement);
    [[m_webView _formDelegate] textDidChangeInTextField:(DOMHTMLInputElement *)inputElement inFrame:kit(element->document()->frame())];
}

static SEL selectorForKeyEvent(KeyboardEvent* event)
{
    // FIXME: This helper function is for the auto-fill code so the bridge can pass a selector to the form delegate.  
    // Eventually, we should move all of the auto-fill code down to WebKit and remove the need for this function by
    // not relying on the selector in the new implementation.
    String key = event->keyIdentifier();
    if (key == "Up")
        return @selector(moveUp:);
    if (key == "Down")
        return @selector(moveDown:);
    if (key == "U+00001B")
        return @selector(cancel:);
    if (key == "U+000009") {
        if (event->shiftKey())
            return @selector(insertBacktab:);
        return @selector(insertTab:);
    }
    if (key == "Enter")
        return @selector(insertNewline:);
    return 0;
}

bool WebEditorClient::doTextFieldCommandFromEvent(WebCore::Element* element, WebCore::KeyboardEvent* event)
{
darin's avatar
darin committed
494
    DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(WebCore::HTMLInputElement*)element];
mjs's avatar
mjs committed
495
496
497
498
499
500
501
502
503
504
505
506
507

    bool result = false;
    FormDelegateLog(inputElement);

    SEL selector = selectorForKeyEvent(event);
    if (selector)
        result = [[m_webView _formDelegate] textField:inputElement doCommandBySelector:selector inFrame:kit(element->document()->frame())];

    return result;
}

void WebEditorClient::textWillBeDeletedInTextField(WebCore::Element* element)
{
darin's avatar
darin committed
508
    DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(WebCore::HTMLInputElement*)element];
mjs's avatar
mjs committed
509
510
511
512
513
514
515
516

    // We're using the deleteBackward selector for all deletion operations since the autofill code treats all deletions the same way.
    FormDelegateLog(inputElement);
    [[m_webView _formDelegate] textField:inputElement doCommandBySelector:@selector(deleteBackward:) inFrame:kit(element->document()->frame())];
}

void WebEditorClient::textDidChangeInTextArea(WebCore::Element* element)
{
darin's avatar
darin committed
517
    DOMHTMLTextAreaElement* textAreaElement = [DOMHTMLTextAreaElement _wrapHTMLTextAreaElement:(WebCore::HTMLTextAreaElement*)element];
mjs's avatar
mjs committed
518
519
520
521

    FormDelegateLog(textAreaElement);
    [[m_webView _formDelegate] textDidChangeInTextArea:textAreaElement inFrame:kit(element->document()->frame())];
}