Patch by Alexey Proskuryakov.
[WebKit-https.git] / WebKitTools / DumpRenderTree / TextInputController.m
1 /*
2  * Copyright (C) 2005 Apple Computer, 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "TextInputController.h"
30
31 #import <AppKit/NSInputManager.h>
32 #import <WebKit/WebDocument.h>
33 #import <WebKit/WebFrame.h>
34 #import <WebKit/WebFrameView.h>
35 #import <WebKit/WebView.h>
36
37 @implementation NSMutableAttributedString (TextInputController)
38
39 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
40 {
41     if (aSelector == @selector(string)
42             || aSelector == @selector(getLength)
43             || aSelector == @selector(attributeNamesAtIndex:)
44             || aSelector == @selector(valueOfAttribute:atIndex:)
45             || aSelector == @selector(addAttribute:value:)
46             || aSelector == @selector(addAttribute:value:from:length:)
47             || aSelector == @selector(addColorAttribute:red:green:blue:alpha:)
48             || aSelector == @selector(addColorAttribute:red:green:blue:alpha:from:length:)
49             || aSelector == @selector(addFontAttribute:fontName:size:)
50             || aSelector == @selector(addFontAttribute:fontName:size:from:length:))
51         return NO;
52     return YES;
53 }
54
55 + (NSString *)webScriptNameForSelector:(SEL)aSelector
56 {
57     if (aSelector == @selector(getLength))
58         return @"length";
59     if (aSelector == @selector(attributeNamesAtIndex:))
60         return @"getAttributeNamesAtIndex";
61     if (aSelector == @selector(valueOfAttribute:atIndex:))
62         return @"getAttributeValueAtIndex";
63     if (aSelector == @selector(addAttribute:value:))
64         return @"addAttribute";
65     if (aSelector == @selector(addAttribute:value:from:length:))
66         return @"addAttributeForRange";
67     if (aSelector == @selector(addColorAttribute:red:green:blue:alpha:))
68         return @"addColorAttribute";
69     if (aSelector == @selector(addColorAttribute:red:green:blue:alpha:from:length:))
70         return @"addColorAttributeForRange";
71     if (aSelector == @selector(addFontAttribute:fontName:size:))
72         return @"addFontAttribute";
73     if (aSelector == @selector(addFontAttribute:fontName:size:from:length:))
74         return @"addFontAttributeForRange";
75
76     return nil;
77 }
78
79 - (int)getLength
80 {
81     return (int)[self length];
82 }
83
84 - (NSArray *)attributeNamesAtIndex:(int)index
85 {
86     NSDictionary *attributes = [self attributesAtIndex:(unsigned)index effectiveRange:nil];
87     return [attributes allKeys];
88 }
89
90 - (id)valueOfAttribute:(NSString *)attrName atIndex:(int)index
91 {
92     return [self attribute:attrName atIndex:(unsigned)index effectiveRange:nil];
93 }
94
95 - (void)addAttribute:(NSString *)attrName value:(id)value
96 {
97     [self addAttribute:attrName value:value range:NSMakeRange(0, [self length])];
98 }
99
100 - (void)addAttribute:(NSString *)attrName value:(id)value from:(int)from length:(int)length
101 {
102     [self addAttribute:attrName value:value range:NSMakeRange((unsigned)from, (unsigned)length)];
103 }
104
105 - (void)addColorAttribute:(NSString *)attrName red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
106 {
107     [self addAttribute:attrName value:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] range:NSMakeRange(0, [self length])];
108 }
109
110 - (void)addColorAttribute:(NSString *)attrName red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha from:(int)from length:(int)length
111 {
112     [self addAttribute:attrName value:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] range:NSMakeRange((unsigned)from, (unsigned)length)];
113 }
114
115 - (void)addFontAttribute:(NSString *)attrName fontName:(NSString *)fontName size:(float)fontSize
116 {
117     [self addAttribute:attrName value:[NSFont fontWithName:fontName size:fontSize] range:NSMakeRange(0, [self length])];
118 }
119
120 - (void)addFontAttribute:(NSString *)attrName fontName:(NSString *)fontName size:(float)fontSize from:(int)from length:(int)length
121 {
122     [self addAttribute:attrName value:[NSFont fontWithName:fontName size:fontSize] range:NSMakeRange((unsigned)from, (unsigned)length)];
123 }
124
125 @end
126
127 @implementation TextInputController
128
129 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
130 {
131     if (aSelector == @selector(insertText:)
132             || aSelector == @selector(doCommand:)
133             || aSelector == @selector(setMarkedText:selectedFrom:length:)
134             || aSelector == @selector(unmarkText)
135             || aSelector == @selector(hasMarkedText)
136             || aSelector == @selector(conversationIdentifier)
137             || aSelector == @selector(substringFrom:length:)
138             || aSelector == @selector(attributedSubstringFrom:length:)
139             || aSelector == @selector(markedRange)
140             || aSelector == @selector(selectedRange)
141             || aSelector == @selector(firstRectForCharactersFrom:length:)
142             || aSelector == @selector(characterIndexForPointX:Y:)
143             || aSelector == @selector(validAttributesForMarkedText)
144             || aSelector == @selector(attributedStringWithString:))
145         return NO;
146     return YES;
147 }
148
149 + (NSString *)webScriptNameForSelector:(SEL)aSelector
150 {
151     if (aSelector == @selector(insertText:))
152         return @"insertText";
153     else if (aSelector == @selector(doCommand:))
154         return @"doCommand";
155     else if (aSelector == @selector(setMarkedText:selectedFrom:length:))
156         return @"setMarkedText";
157     else if (aSelector == @selector(substringFrom:length:))
158         return @"substringFromRange";
159     else if (aSelector == @selector(attributedSubstringFrom:length:))
160         return @"attributedSubstringFromRange";
161     else if (aSelector == @selector(firstRectForCharactersFrom:length:))
162         return @"firstRectForCharacterRange";
163     else if (aSelector == @selector(characterIndexForPointX:Y:))
164         return @"characterIndexForPoint";
165     else if (aSelector == @selector(attributedStringWithString:))
166         return @"makeAttributedString"; // just a factory method, doesn't call into NSTextInput
167
168     return nil;
169 }
170
171 - (id)initWithWebView:(WebView *)wv
172 {
173     self = [super init];
174     webView = wv;
175     return self;
176 }
177
178 - (NSObject <NSTextInput> *)textInput
179 {
180     NSView <NSTextInput> *view = [[[webView mainFrame] frameView] documentView];
181     return [view conformsToProtocol:@protocol(NSTextInput)] ? view : nil;
182 }
183
184 - (void)insertText:(id)aString
185 {
186     NSObject <NSTextInput> *textInput = [self textInput];
187
188     if (textInput)
189         [textInput insertText:aString];
190 }
191
192 - (void)doCommand:(NSString *)aCommand
193 {
194     NSObject <NSTextInput> *textInput = [self textInput];
195
196     if (textInput)
197         [textInput doCommandBySelector:NSSelectorFromString(aCommand)];
198 }
199
200 - (void)setMarkedText:(NSString *)aString selectedFrom:(int)from length:(int)length
201 {
202     NSObject <NSTextInput> *textInput = [self textInput];
203  
204     if (textInput)
205         [textInput setMarkedText:aString selectedRange:NSMakeRange(from, length)];
206 }
207
208 - (void)unmarkText
209 {
210     NSObject <NSTextInput> *textInput = [self textInput];
211
212     if (textInput)
213         [textInput unmarkText];
214 }
215
216 - (BOOL)hasMarkedText
217 {
218     NSObject <NSTextInput> *textInput = [self textInput];
219
220     if (textInput)
221         return [textInput hasMarkedText];
222
223     return FALSE;
224 }
225
226 - (long)conversationIdentifier
227 {
228     NSObject <NSTextInput> *textInput = [self textInput];
229
230     if (textInput)
231         return [textInput conversationIdentifier];
232
233     return 0;
234 }
235
236 - (NSString *)substringFrom:(int)from length:(int)length
237 {
238     NSObject <NSTextInput> *textInput = [self textInput];
239
240     if (textInput)
241         return [[textInput attributedSubstringFromRange:NSMakeRange(from, length)] string];
242     
243     return @"";
244 }
245
246 - (NSMutableAttributedString *)attributedSubstringFrom:(int)from length:(int)length
247 {
248     NSObject <NSTextInput> *textInput = [self textInput];
249
250     NSMutableAttributedString *ret = [[[NSMutableAttributedString alloc] init] autorelease];
251
252     if (textInput)
253         [ret setAttributedString:[textInput attributedSubstringFromRange:NSMakeRange(from, length)]];
254     
255     return ret;
256 }
257
258 - (NSArray *)markedRange
259 {
260     NSObject <NSTextInput> *textInput = [self textInput];
261
262     if (textInput) {
263         NSRange range = [textInput markedRange];
264         return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
265     }
266
267     return nil;
268 }
269
270 - (NSArray *)selectedRange
271 {
272     NSObject <NSTextInput> *textInput = [self textInput];
273
274     if (textInput) {
275         NSRange range = [textInput selectedRange];
276         return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
277     }
278
279     return nil;
280 }
281   
282
283 - (NSArray *)firstRectForCharactersFrom:(int)from length:(int)length
284 {
285     NSObject <NSTextInput> *textInput = [self textInput];
286
287     if (textInput) {
288         NSRect rect = [textInput firstRectForCharacterRange:NSMakeRange(from, length)];
289         return [NSArray arrayWithObjects:
290                     [NSNumber numberWithFloat:rect.origin.x],
291                     [NSNumber numberWithFloat:rect.origin.y],
292                     [NSNumber numberWithFloat:rect.size.width],
293                     [NSNumber numberWithFloat:rect.size.height],
294                     nil];
295     }
296
297     return nil;
298 }
299
300 - (int)characterIndexForPointX:(float)x Y:(float)y
301 {
302     NSObject <NSTextInput> *textInput = [self textInput];
303
304     if (textInput)
305         return [textInput characterIndexForPoint:NSMakePoint(x, y)];
306
307     return 0;
308 }
309
310 - (NSArray *)validAttributesForMarkedText
311 {
312     NSObject <NSTextInput> *textInput = [self textInput];
313
314     if (textInput)
315         return [textInput validAttributesForMarkedText];
316
317     return nil;
318 }
319
320 - (NSMutableAttributedString *)attributedStringWithString:(NSString *)aString
321 {
322     NSMutableAttributedString *ret = [[[NSMutableAttributedString alloc] init] autorelease];
323     [ret setAttributedString:[[[NSAttributedString alloc] initWithString:aString] autorelease]];
324     return ret;
325 }
326
327 @end