author | chegar |
Sun, 17 Aug 2014 15:54:13 +0100 | |
changeset 25859 | 3317bb8137f4 |
parent 14342 | jdk/src/macosx/native/apple/applescript/AS_NS_ConversionUtils.m@8435a30053c1 |
permissions | -rw-r--r-- |
12047 | 1 |
/* |
14342
8435a30053c1
7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents:
12047
diff
changeset
|
2 |
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. |
12047 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
// |
|
27 |
// Most of this is adapted from Ken Ferry's KFAppleScript Additions, contributed with permission |
|
28 |
// http://homepage.mac.com/kenferry/software.html |
|
29 |
// |
|
30 |
||
31 |
#import "AS_NS_ConversionUtils.h" |
|
32 |
||
33 |
#import <Cocoa/Cocoa.h> |
|
34 |
#import <Carbon/Carbon.h> |
|
35 |
||
36 |
||
37 |
@interface NSAppleEventDescriptor (JavaAppleScriptEngineAdditionsPrivate) |
|
38 |
||
39 |
// just returns self. This means that you can pass custom descriptors |
|
40 |
// to -[NSAppleScript executeHandler:error:withParameters:]. |
|
41 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
42 |
||
43 |
// working with primitive descriptor types |
|
44 |
+ (id)descriptorWithInt16:(SInt16)val; |
|
45 |
- (SInt16)int16Value; |
|
46 |
+ (id)descriptorWithUnsignedInt32:(UInt32)val; |
|
47 |
- (UInt32)unsignedInt32Value; |
|
48 |
+ (id)descriptorWithFloat32:(Float32)val; |
|
49 |
- (Float32)float32Value; |
|
50 |
+ (id)descriptorWithFloat64:(Float64)val; |
|
51 |
- (Float64)float64Value; |
|
52 |
+ (id)descriptorWithLongDateTime:(LongDateTime)val; |
|
53 |
- (LongDateTime)longDateTimeValue; |
|
54 |
||
55 |
||
56 |
// These are the methods for converting AS objects to objective-C objects. |
|
57 |
// -[NSAppleEventDescriptor objCObjectValue] is the general method for converting |
|
58 |
// AS objects to ObjC objects, and is called by -[NSAppleScript executeHandler:error:withParameters:]. |
|
59 |
// It does no work itself. It finds a handler based on the type of the descriptor and lets that |
|
60 |
// handler object do the work. If there is no handler type registered for a the type of a descriptor, |
|
61 |
// the raw descriptor is returned. |
|
62 |
// |
|
63 |
// You can designate a handlers for descriptor types with |
|
64 |
// +[NSAppleEventDescriptor registerConversionHandler:selector:forDescriptorTypes:]. Please note |
|
65 |
// that this method does _not_ retain the handler object (for now anyway). The selector should |
|
66 |
// take a single argument, a descriptor to translate, and should return an object. An example such |
|
67 |
// selector is @selector(dictionaryWithAEDesc:), for which the handler object would be [NSDictionary class]. |
|
68 |
// |
|
69 |
// A number of handlers are designated by default. The methods and objects can be easily inferred (or check |
|
70 |
// the implementation), but the automatically handled types are |
|
71 |
// typeUnicodeText, |
|
72 |
// typeText, |
|
73 |
// typeUTF8Text, |
|
74 |
// typeCString, |
|
75 |
// typeChar, |
|
76 |
// typeBoolean, |
|
77 |
// typeTrue, |
|
78 |
// typeFalse, |
|
79 |
// typeSInt16, |
|
80 |
// typeSInt32, |
|
81 |
// typeUInt32, |
|
82 |
// typeSInt64, |
|
83 |
// typeIEEE32BitFloatingPoint, |
|
84 |
// typeIEEE64BitFloatingPoint, |
|
85 |
// type128BitFloatingPoint, |
|
86 |
// typeAEList, |
|
87 |
// typeAERecord, |
|
88 |
// typeLongDateTime, |
|
89 |
// typeNull. |
|
90 |
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ...; |
|
91 |
+ (void) jaseSetUpHandlerDict; |
|
92 |
@end |
|
93 |
||
94 |
// wrap the NSAppleEventDescriptor string methods |
|
95 |
@interface NSString (JavaAppleScriptEngineAdditions) |
|
96 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
97 |
+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
98 |
@end |
|
99 |
||
100 |
// wrap the NSAppleEventDescriptor longDateTime methods |
|
101 |
@interface NSDate (JavaAppleScriptEngineAdditions) |
|
102 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
103 |
+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
104 |
@end |
|
105 |
||
106 |
// these are fairly complicated methods, due to having to try to match up the various |
|
107 |
// AS number types (see NSAppleEventDescriptor for the primitive number methods) |
|
108 |
// with NSNumber variants. For complete behavior it's best to look at the implementation. |
|
109 |
// Some notes: |
|
110 |
// NSNumbers created with numberWithBool should be correctly translated to AS booleans and vice versa. |
|
111 |
// NSNumbers created with large integer types may have to be translated to AS doubles, |
|
112 |
// so be careful if checking equality (you may have to check equality within epsilon). |
|
113 |
// Since NSNumbers can't remember if they were created with an unsigned value, |
|
114 |
// [[NSNumber numberWithUnsignedChar:255] aeDescriptorValue] is going to get you an AS integer |
|
115 |
// with value -1. If you really need a descriptor with an unsigned value, you'll need to do it |
|
116 |
// manually using the primitive methods on NSAppleEventDescriptor. The resulting descriptor |
|
117 |
// can still be passed to AS with -[NSAppleScript executeHandler:error:withParameters:]. |
|
118 |
@interface NSNumber (JavaAppleScriptEngineAdditions) |
|
119 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
120 |
+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
121 |
@end |
|
122 |
||
123 |
// Here we're following the behavior described in the CocoaScripting release note. |
|
124 |
// |
|
125 |
// NSPoint -> list of two numbers: {x, y} |
|
126 |
// NSRange -> list of two numbers: {begin offset, end offset} |
|
127 |
// NSRect -> list of four numbers: {left, bottom, right, top} |
|
128 |
// NSSize -> list of two numbers: {width, height} |
|
129 |
@interface NSValue (JavaAppleScriptEngineAdditions) |
|
130 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
131 |
@end |
|
132 |
||
133 |
// No need for ObjC -> AS conversion here, we fall through to NSObject as a collection. |
|
134 |
// For AS -> ObjC conversion, we build an array using the primitive list methods on |
|
135 |
// NSAppleEventDescriptor. |
|
136 |
@interface NSArray (JavaAppleScriptEngineAdditions) |
|
137 |
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
138 |
@end |
|
139 |
||
140 |
||
141 |
// Please see the CocoaScripting release note for behavior. It's kind of complicated. |
|
142 |
// |
|
143 |
// methods wrap the primitive record methods on NSAppleEventDescriptor. |
|
144 |
@interface NSDictionary (JavaAppleScriptEngineAdditions) |
|
145 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
146 |
+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
147 |
@end |
|
148 |
||
149 |
// be aware that a null descriptor does not correspond to the 'null' keyword in |
|
150 |
// AppleScript - it's more like nothing at all. For example, the return |
|
151 |
// from an empty handler. |
|
152 |
@interface NSNull (JavaAppleScriptEngineAdditions) |
|
153 |
- (NSAppleEventDescriptor *)aeDescriptorValue; |
|
154 |
+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc; |
|
155 |
@end |
|
156 |
||
157 |
||
158 |
@interface NSNumber (JavaAppleScriptEngineAdditionsPrivate) |
|
159 |
+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes; |
|
160 |
+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes; |
|
161 |
+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes; |
|
162 |
@end |
|
163 |
||
164 |
||
165 |
@implementation NSObject (JavaAppleScriptEngineAdditions) |
|
166 |
||
167 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
168 |
// collections go to lists |
|
169 |
if (![self respondsToSelector:@selector(objectEnumerator)]) { |
|
170 |
// encode the description as a fallback - this is pretty useless, only helpful for debugging |
|
171 |
return [[self description] aeDescriptorValue]; |
|
172 |
} |
|
173 |
||
174 |
NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor listDescriptor]; |
|
175 |
NSEnumerator *objectEnumerator = [(id)self objectEnumerator]; |
|
176 |
||
177 |
unsigned int i = 1; // apple event descriptors are 1-indexed |
|
178 |
id currentObject; |
|
179 |
while((currentObject = [objectEnumerator nextObject]) != nil) { |
|
180 |
[resultDesc insertDescriptor:[currentObject aeDescriptorValue] atIndex:i++]; |
|
181 |
} |
|
182 |
||
183 |
return resultDesc; |
|
184 |
} |
|
185 |
||
186 |
@end |
|
187 |
||
188 |
||
189 |
@implementation NSArray (JavaAppleScriptEngineAdditions) |
|
190 |
||
191 |
// don't need to override aeDescriptorValue, the NSObject will treat the array as a collection |
|
192 |
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
193 |
NSAppleEventDescriptor *listDesc = [desc coerceToDescriptorType:typeAEList]; |
|
194 |
NSMutableArray *resultArray = [NSMutableArray array]; |
|
195 |
||
196 |
// apple event descriptors are 1-indexed |
|
197 |
unsigned int listCount = [listDesc numberOfItems]; |
|
198 |
unsigned int i; |
|
199 |
for (i = 1; i <= listCount; i++) { |
|
200 |
[resultArray addObject:[[listDesc descriptorAtIndex:i] objCObjectValue]]; |
|
201 |
} |
|
202 |
||
203 |
return resultArray; |
|
204 |
} |
|
205 |
||
206 |
@end |
|
207 |
||
208 |
||
209 |
@implementation NSDictionary (JavaAppleScriptEngineAdditions) |
|
210 |
||
211 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
212 |
NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor recordDescriptor]; |
|
213 |
NSMutableArray *userFields = [NSMutableArray array]; |
|
214 |
NSArray *keys = [self allKeys]; |
|
215 |
||
216 |
unsigned int keyCount = [keys count]; |
|
217 |
unsigned int i; |
|
218 |
for (i = 0; i < keyCount; i++) { |
|
219 |
id key = [keys objectAtIndex:i]; |
|
220 |
||
221 |
if ([key isKindOfClass:[NSNumber class]]) { |
|
222 |
[resultDesc setDescriptor:[[self objectForKey:key] aeDescriptorValue] forKeyword:[(NSNumber *)key intValue]]; |
|
223 |
} else if ([key isKindOfClass:[NSString class]]) { |
|
224 |
[userFields addObject:key]; |
|
225 |
[userFields addObject:[self objectForKey:key]]; |
|
226 |
} |
|
227 |
} |
|
228 |
||
229 |
if ([userFields count] > 0) { |
|
230 |
[resultDesc setDescriptor:[userFields aeDescriptorValue] forKeyword:keyASUserRecordFields]; |
|
231 |
} |
|
232 |
||
233 |
return resultDesc; |
|
234 |
} |
|
235 |
||
236 |
+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
237 |
NSAppleEventDescriptor *recDescriptor = [desc coerceToDescriptorType:typeAERecord]; |
|
238 |
NSMutableDictionary *resultDict = [NSMutableDictionary dictionary]; |
|
239 |
||
240 |
// NSAppleEventDescriptor uses 1 indexing |
|
241 |
unsigned int recordCount = [recDescriptor numberOfItems]; |
|
242 |
unsigned int recordIndex; |
|
243 |
for (recordIndex = 1; recordIndex <= recordCount; recordIndex++) { |
|
244 |
AEKeyword keyword = [recDescriptor keywordForDescriptorAtIndex:recordIndex]; |
|
245 |
||
246 |
if(keyword == keyASUserRecordFields) { |
|
247 |
NSAppleEventDescriptor *listDescriptor = [recDescriptor descriptorAtIndex:recordIndex]; |
|
248 |
||
249 |
// NSAppleEventDescriptor uses 1 indexing |
|
250 |
unsigned int listCount = [listDescriptor numberOfItems]; |
|
251 |
unsigned int listIndex; |
|
252 |
for (listIndex = 1; listIndex <= listCount; listIndex += 2) { |
|
253 |
id keyObj = [[listDescriptor descriptorAtIndex:listIndex] objCObjectValue]; |
|
254 |
id valObj = [[listDescriptor descriptorAtIndex:listIndex+1] objCObjectValue]; |
|
255 |
||
256 |
[resultDict setObject:valObj forKey:keyObj]; |
|
257 |
} |
|
258 |
} else { |
|
259 |
id keyObj = [NSNumber numberWithInt:keyword]; |
|
260 |
id valObj = [[recDescriptor descriptorAtIndex:recordIndex] objCObjectValue]; |
|
261 |
||
262 |
[resultDict setObject:valObj forKey:keyObj]; |
|
263 |
} |
|
264 |
} |
|
265 |
||
266 |
return resultDict; |
|
267 |
} |
|
268 |
||
269 |
@end |
|
270 |
||
271 |
||
272 |
@implementation NSString (JavaAppleScriptEngineAdditions) |
|
273 |
||
274 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
275 |
return [NSAppleEventDescriptor descriptorWithString:self]; |
|
276 |
} |
|
277 |
||
278 |
+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
279 |
return [desc stringValue]; |
|
280 |
} |
|
281 |
||
282 |
+ (NSString *)versionWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
283 |
const AEDesc *aeDesc = [desc aeDesc]; |
|
284 |
VersRec v; |
|
285 |
AEGetDescData(aeDesc, &v, sizeof(v)); |
|
286 |
return [[[NSString alloc] initWithBytes:&v.shortVersion[1] length:StrLength(v.shortVersion) encoding:NSUTF8StringEncoding] autorelease]; |
|
287 |
} |
|
288 |
||
289 |
@end |
|
290 |
||
291 |
||
292 |
@implementation NSNull (JavaAppleScriptEngineAdditions) |
|
293 |
||
294 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
295 |
return [NSAppleEventDescriptor nullDescriptor]; |
|
296 |
} |
|
297 |
||
298 |
+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
299 |
return [NSNull null]; |
|
300 |
} |
|
301 |
||
302 |
@end |
|
303 |
||
304 |
||
305 |
@implementation NSDate (JavaAppleScriptEngineAdditions) |
|
306 |
||
307 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
308 |
LongDateTime ldt; |
|
309 |
UCConvertCFAbsoluteTimeToLongDateTime(CFDateGetAbsoluteTime((CFDateRef)self), &ldt); |
|
310 |
return [NSAppleEventDescriptor descriptorWithLongDateTime:ldt]; |
|
311 |
} |
|
312 |
||
313 |
+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
314 |
CFAbsoluteTime absTime; |
|
315 |
UCConvertLongDateTimeToCFAbsoluteTime([desc longDateTimeValue], &absTime); |
|
316 |
NSDate *resultDate = (NSDate *)CFDateCreate(NULL, absTime); |
|
317 |
return [resultDate autorelease]; |
|
318 |
} |
|
319 |
||
320 |
@end |
|
321 |
||
322 |
||
323 |
||
324 |
static inline int areEqualEncodings(const char *enc1, const char *enc2) { |
|
325 |
return (strcmp(enc1, enc2) == 0); |
|
326 |
} |
|
327 |
||
328 |
@implementation NSNumber (JavaAppleScriptEngineAdditions) |
|
329 |
||
330 |
-(id)jaseDescriptorValueWithFloatP:(void *)float_p byteCount:(int)bytes { |
|
331 |
float floatVal; |
|
332 |
if (bytes < sizeof(Float32)) { |
|
333 |
floatVal = [self floatValue]; |
|
334 |
float_p = &floatVal; |
|
335 |
bytes = sizeof(floatVal); |
|
336 |
} |
|
337 |
||
338 |
double doubleVal; |
|
339 |
if (bytes > sizeof(Float64)) { |
|
340 |
doubleVal = [self doubleValue]; |
|
341 |
float_p = &doubleVal; |
|
342 |
bytes = sizeof(doubleVal); |
|
343 |
} |
|
344 |
||
345 |
if (bytes == sizeof(Float32)) { |
|
346 |
return [NSAppleEventDescriptor descriptorWithFloat32:*(Float32 *)float_p]; |
|
347 |
} |
|
348 |
||
349 |
if (bytes == sizeof(Float64)) { |
|
350 |
return [NSAppleEventDescriptor descriptorWithFloat64:*(Float64 *)float_p]; |
|
351 |
} |
|
352 |
||
353 |
[NSException raise:NSInvalidArgumentException |
|
354 |
format:@"Cannot create an NSAppleEventDescriptor for float with %d bytes of data.", bytes]; |
|
355 |
||
356 |
return nil; |
|
357 |
} |
|
358 |
||
359 |
-(id)jaseDescriptorValueWithSignedIntP:(void *)int_p byteCount:(int)bytes { |
|
360 |
int intVal; |
|
361 |
||
362 |
if (bytes < sizeof(SInt16)) { |
|
363 |
intVal = [self intValue]; |
|
364 |
int_p = &intVal; |
|
365 |
bytes = sizeof(intVal); |
|
366 |
} |
|
367 |
||
368 |
if (bytes == sizeof(SInt16)) { |
|
369 |
return [NSAppleEventDescriptor descriptorWithInt16:*(SInt16 *)int_p]; |
|
370 |
} |
|
371 |
||
372 |
if (bytes == sizeof(SInt32)) { |
|
373 |
return [NSAppleEventDescriptor descriptorWithInt32:*(SInt32 *)int_p]; |
|
374 |
} |
|
375 |
||
376 |
double val = [self doubleValue]; |
|
377 |
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)]; |
|
378 |
} |
|
379 |
||
380 |
-(id)jaseDescriptorValueWithUnsignedIntP:(void *)int_p byteCount:(int)bytes { |
|
381 |
unsigned int uIntVal; |
|
382 |
||
383 |
if (bytes < sizeof(UInt32)) { |
|
384 |
uIntVal = [self unsignedIntValue]; |
|
385 |
int_p = &uIntVal; |
|
386 |
bytes = sizeof(uIntVal); |
|
387 |
} |
|
388 |
||
389 |
if (bytes == sizeof(UInt32)) { |
|
390 |
return [NSAppleEventDescriptor descriptorWithUnsignedInt32:*(UInt32 *)int_p]; |
|
391 |
} |
|
392 |
||
393 |
double val = (double)[self unsignedLongLongValue]; |
|
394 |
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)]; |
|
395 |
} |
|
396 |
||
397 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
398 |
// NSNumber is unfortunately complicated, because the applescript |
|
399 |
// type we should use depends on the c type that our NSNumber corresponds to |
|
400 |
||
401 |
const char *type = [self objCType]; |
|
402 |
||
403 |
// convert |
|
404 |
if (areEqualEncodings(type, @encode(BOOL))) { |
|
405 |
return [NSAppleEventDescriptor descriptorWithBoolean:[self boolValue]]; |
|
406 |
} |
|
407 |
||
408 |
if (areEqualEncodings(type, @encode(char))) { |
|
409 |
char val = [self charValue]; |
|
410 |
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)]; |
|
411 |
} |
|
412 |
||
413 |
if (areEqualEncodings(type, @encode(short))) { |
|
414 |
short val = [self shortValue]; |
|
415 |
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)]; |
|
416 |
} |
|
417 |
||
418 |
if (areEqualEncodings(type, @encode(int))) { |
|
419 |
int val = [self intValue]; |
|
420 |
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)]; |
|
421 |
} |
|
422 |
||
423 |
if (areEqualEncodings(type, @encode(long))) { |
|
424 |
long val = [self longValue]; |
|
425 |
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)]; |
|
426 |
} |
|
427 |
||
428 |
if (areEqualEncodings(type, @encode(long long))) { |
|
429 |
long long val = [self longLongValue]; |
|
430 |
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)]; |
|
431 |
} |
|
432 |
||
433 |
if (areEqualEncodings(type, @encode(unsigned char))) { |
|
434 |
unsigned char val = [self unsignedCharValue]; |
|
435 |
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
436 |
} |
|
437 |
||
438 |
if (areEqualEncodings(type, @encode(unsigned short))) { |
|
439 |
unsigned short val = [self unsignedShortValue]; |
|
440 |
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
441 |
} |
|
442 |
||
443 |
if (areEqualEncodings(type, @encode(unsigned int))) { |
|
444 |
unsigned int val = [self unsignedIntValue]; |
|
445 |
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
446 |
} |
|
447 |
||
448 |
if (areEqualEncodings(type, @encode(unsigned long))) { |
|
449 |
unsigned long val = [self unsignedLongValue]; |
|
450 |
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
451 |
} |
|
452 |
||
453 |
if (areEqualEncodings(type, @encode(unsigned long long))) { |
|
454 |
unsigned long long val = [self unsignedLongLongValue]; |
|
455 |
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
456 |
} |
|
457 |
||
458 |
if (areEqualEncodings(type, @encode(float))) { |
|
459 |
float val = [self floatValue]; |
|
460 |
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)]; |
|
461 |
} |
|
462 |
||
463 |
if (areEqualEncodings(type, @encode(double))) { |
|
464 |
double val = [self doubleValue]; |
|
465 |
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)]; |
|
466 |
} |
|
467 |
||
468 |
[NSException raise:@"jaseUnsupportedAEDescriptorConversion" |
|
469 |
format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type]; |
|
470 |
||
471 |
return nil; |
|
472 |
} |
|
473 |
||
474 |
+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
475 |
DescType type = [desc descriptorType]; |
|
476 |
||
477 |
if ((type == typeTrue) || (type == typeFalse) || (type == typeBoolean)) { |
|
478 |
return [NSNumber numberWithBool:[desc booleanValue]]; |
|
479 |
} |
|
480 |
||
481 |
if (type == typeSInt16) { |
|
482 |
SInt16 val = [desc int16Value]; |
|
483 |
return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)]; |
|
484 |
} |
|
485 |
||
486 |
if (type == typeSInt32) { |
|
487 |
SInt32 val = [desc int32Value]; |
|
488 |
return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)]; |
|
489 |
} |
|
490 |
||
491 |
if (type == typeUInt32) { |
|
492 |
UInt32 val = [desc unsignedInt32Value]; |
|
493 |
return [NSNumber jaseNumberWithUnsignedIntP:&val byteCount:sizeof(val)]; |
|
494 |
} |
|
495 |
||
496 |
if (type == typeIEEE32BitFloatingPoint) { |
|
497 |
Float32 val = [desc float32Value]; |
|
498 |
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)]; |
|
499 |
} |
|
500 |
||
501 |
if (type == typeIEEE64BitFloatingPoint) { |
|
502 |
Float64 val = [desc float64Value]; |
|
503 |
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)]; |
|
504 |
} |
|
505 |
||
506 |
// try to coerce to 64bit floating point |
|
507 |
desc = [desc coerceToDescriptorType:typeIEEE64BitFloatingPoint]; |
|
508 |
if (desc != nil) { |
|
509 |
Float64 val = [desc float64Value]; |
|
510 |
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)]; |
|
511 |
} |
|
512 |
||
513 |
[NSException raise:@"jaseUnsupportedAEDescriptorConversion" |
|
514 |
format:@"JavaAppleScriptEngineAdditions: conversion of an NSAppleEventDescriptor with objCType '%s' to an aeDescriptor is not supported.", type]; |
|
515 |
||
516 |
return nil; |
|
517 |
} |
|
518 |
||
519 |
+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes { |
|
520 |
if (bytes == sizeof(char)) { |
|
521 |
return [NSNumber numberWithChar:*(char *)int_p]; |
|
522 |
} |
|
523 |
||
524 |
if (bytes == sizeof(short)) { |
|
525 |
return [NSNumber numberWithShort:*(short *)int_p]; |
|
526 |
} |
|
527 |
||
528 |
if (bytes == sizeof(int)) { |
|
529 |
return [NSNumber numberWithInt:*(int *)int_p]; |
|
530 |
} |
|
531 |
||
532 |
if (bytes == sizeof(long)) { |
|
533 |
return [NSNumber numberWithLong:*(long *)int_p]; |
|
534 |
} |
|
535 |
||
536 |
if (bytes == sizeof(long long)) { |
|
537 |
return [NSNumber numberWithLongLong:*(long long *)int_p]; |
|
538 |
} |
|
539 |
||
540 |
[NSException raise:NSInvalidArgumentException |
|
541 |
format:@"NSNumber jaseNumberWithSignedIntP:byteCount: number with %i bytes not supported.", bytes]; |
|
542 |
||
543 |
return nil; |
|
544 |
} |
|
545 |
||
546 |
+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes { |
|
547 |
if (bytes == sizeof(unsigned char)) { |
|
548 |
return [NSNumber numberWithUnsignedChar:*(unsigned char *)int_p]; |
|
549 |
} |
|
550 |
||
551 |
if (bytes == sizeof(unsigned short)) { |
|
552 |
return [NSNumber numberWithUnsignedShort:*(unsigned short *)int_p]; |
|
553 |
} |
|
554 |
||
555 |
if (bytes == sizeof(unsigned int)) { |
|
556 |
return [NSNumber numberWithUnsignedInt:*(unsigned int *)int_p]; |
|
557 |
} |
|
558 |
||
559 |
if (bytes == sizeof(unsigned long)) { |
|
560 |
return [NSNumber numberWithUnsignedLong:*(unsigned long *)int_p]; |
|
561 |
} |
|
562 |
||
563 |
if (bytes == sizeof(unsigned long long)) { |
|
564 |
return [NSNumber numberWithUnsignedLongLong:*(unsigned long long *)int_p]; |
|
565 |
} |
|
566 |
||
567 |
[NSException raise:NSInvalidArgumentException |
|
568 |
format:@"NSNumber numberWithUnsignedInt:byteCount: number with %i bytes not supported.", bytes]; |
|
569 |
||
570 |
return nil; |
|
571 |
} |
|
572 |
||
573 |
+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes { |
|
574 |
if (bytes == sizeof(float)) { |
|
575 |
return [NSNumber numberWithFloat:*(float *)float_p]; |
|
576 |
} |
|
577 |
||
578 |
if (bytes == sizeof(double)) { |
|
579 |
return [NSNumber numberWithFloat:*(double *)float_p]; |
|
580 |
} |
|
581 |
||
582 |
[NSException raise:NSInvalidArgumentException |
|
583 |
format:@"NSNumber numberWithFloat:byteCount: floating point number with %i bytes not supported.", bytes]; |
|
584 |
||
585 |
return nil; |
|
586 |
} |
|
587 |
||
588 |
@end |
|
589 |
||
590 |
@implementation NSValue (JavaAppleScriptEngineAdditions) |
|
591 |
||
592 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
593 |
const char *type = [self objCType]; |
|
594 |
||
595 |
if (areEqualEncodings(type, @encode(NSSize))) { |
|
596 |
NSSize size = [self sizeValue]; |
|
597 |
return [[NSArray arrayWithObjects: |
|
598 |
[NSNumber numberWithFloat:size.width], |
|
599 |
[NSNumber numberWithFloat:size.height], nil] aeDescriptorValue]; |
|
600 |
} |
|
601 |
||
602 |
if (areEqualEncodings(type, @encode(NSPoint))) { |
|
603 |
NSPoint point = [self pointValue]; |
|
604 |
return [[NSArray arrayWithObjects: |
|
605 |
[NSNumber numberWithFloat:point.x], |
|
606 |
[NSNumber numberWithFloat:point.y], nil] aeDescriptorValue]; |
|
607 |
} |
|
608 |
||
609 |
if (areEqualEncodings(type, @encode(NSRange))) { |
|
610 |
NSRange range = [self rangeValue]; |
|
611 |
return [[NSArray arrayWithObjects: |
|
612 |
[NSNumber numberWithUnsignedInt:range.location], |
|
613 |
[NSNumber numberWithUnsignedInt:range.location + range.length], nil] aeDescriptorValue]; |
|
614 |
} |
|
615 |
||
616 |
if (areEqualEncodings(type, @encode(NSRect))) { |
|
617 |
NSRect rect = [self rectValue]; |
|
618 |
return [[NSArray arrayWithObjects: |
|
619 |
[NSNumber numberWithFloat:rect.origin.x], |
|
620 |
[NSNumber numberWithFloat:rect.origin.y], |
|
621 |
[NSNumber numberWithFloat:rect.origin.x + rect.size.width], |
|
622 |
[NSNumber numberWithFloat:rect.origin.y + rect.size.height], nil] aeDescriptorValue]; |
|
623 |
} |
|
624 |
||
625 |
[NSException raise:@"jaseUnsupportedAEDescriptorConversion" |
|
626 |
format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type]; |
|
627 |
||
628 |
return nil; |
|
629 |
} |
|
630 |
||
631 |
@end |
|
632 |
||
633 |
||
634 |
@implementation NSImage (JavaAppleScriptEngineAdditions) |
|
635 |
||
636 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
637 |
NSData *data = [self TIFFRepresentation]; |
|
638 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeTIFF data:data]; |
|
639 |
} |
|
640 |
||
641 |
+ (NSImage *)imageWithAEDesc:(NSAppleEventDescriptor *)desc { |
|
642 |
const AEDesc *d = [desc aeDesc]; |
|
643 |
NSMutableData *data = [NSMutableData dataWithLength:AEGetDescDataSize(d)]; |
|
644 |
AEGetDescData(d, [data mutableBytes], [data length]); |
|
645 |
return [[[NSImage alloc] initWithData:data] autorelease]; |
|
646 |
} |
|
647 |
||
648 |
@end |
|
649 |
||
650 |
||
651 |
||
652 |
@implementation NSAppleEventDescriptor (JavaAppleScriptEngineAdditions) |
|
653 |
||
654 |
// we're going to leak this. It doesn't matter much for running apps, but |
|
655 |
// for developers it might be nice to try to dispose of it (so it would not clutter the |
|
656 |
// output when testing for leaks) |
|
657 |
static NSMutableDictionary *handlerDict = nil; |
|
658 |
||
659 |
- (id)objCObjectValue { |
|
660 |
if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict]; |
|
661 |
||
662 |
id returnObj; |
|
663 |
DescType type = [self descriptorType]; |
|
664 |
NSInvocation *handlerInvocation = [handlerDict objectForKey:[NSValue valueWithBytes:&type objCType:@encode(DescType)]]; |
|
665 |
if (handlerInvocation == nil) { |
|
666 |
if (type == typeType) { |
|
667 |
DescType subType; |
|
668 |
AEGetDescData([self aeDesc], &subType, sizeof(subType)); |
|
669 |
if (subType == typeNull) return [NSNull null]; |
|
670 |
} |
|
671 |
// return raw apple event descriptor if no handler is registered |
|
672 |
returnObj = self; |
|
673 |
} else { |
|
674 |
[handlerInvocation setArgument:&self atIndex:2]; |
|
675 |
[handlerInvocation invoke]; |
|
676 |
[handlerInvocation getReturnValue:&returnObj]; |
|
677 |
} |
|
678 |
||
679 |
return returnObj; |
|
680 |
} |
|
681 |
||
682 |
// FIXME - error checking, non nil handler |
|
683 |
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ... { |
|
684 |
if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict]; |
|
685 |
||
686 |
NSInvocation *handlerInvocation = [NSInvocation invocationWithMethodSignature:[anObject methodSignatureForSelector:aSelector]]; |
|
687 |
[handlerInvocation setTarget:anObject]; |
|
688 |
[handlerInvocation setSelector:aSelector]; |
|
689 |
||
690 |
DescType aType = firstType; |
|
691 |
va_list typesList; |
|
692 |
va_start(typesList, firstType); |
|
693 |
do { |
|
694 |
NSValue *type = [NSValue valueWithBytes:&aType objCType:@encode(DescType)]; |
|
695 |
[handlerDict setObject:handlerInvocation forKey:type]; |
|
696 |
} while((aType = va_arg(typesList, DescType)) != 0); |
|
697 |
va_end(typesList); |
|
698 |
} |
|
699 |
||
700 |
||
701 |
- (NSAppleEventDescriptor *)aeDescriptorValue { |
|
702 |
return self; |
|
703 |
} |
|
704 |
||
705 |
+ (id)descriptorWithInt16:(SInt16)val { |
|
706 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt16 bytes:&val length:sizeof(val)]; |
|
707 |
} |
|
708 |
||
709 |
- (SInt16)int16Value { |
|
710 |
SInt16 retValue; |
|
711 |
[[[self coerceToDescriptorType:typeSInt16] data] getBytes:&retValue]; |
|
712 |
return retValue; |
|
713 |
} |
|
714 |
||
715 |
+ (id)descriptorWithUnsignedInt32:(UInt32)val { |
|
716 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeUInt32 bytes:&val length:sizeof(val)]; |
|
717 |
} |
|
718 |
||
719 |
- (UInt32)unsignedInt32Value { |
|
720 |
UInt32 retValue; |
|
721 |
[[[self coerceToDescriptorType:typeUInt32] data] getBytes:&retValue]; |
|
722 |
return retValue; |
|
723 |
} |
|
724 |
||
725 |
||
726 |
+ (id)descriptorWithFloat32:(Float32)val { |
|
727 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE32BitFloatingPoint bytes:&val length:sizeof(val)]; |
|
728 |
} |
|
729 |
||
730 |
- (Float32)float32Value { |
|
731 |
Float32 retValue; |
|
732 |
[[[self coerceToDescriptorType:typeIEEE32BitFloatingPoint] data] getBytes:&retValue]; |
|
733 |
return retValue; |
|
734 |
} |
|
735 |
||
736 |
||
737 |
+ (id)descriptorWithFloat64:(Float64)val { |
|
738 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&val length:sizeof(val)]; |
|
739 |
} |
|
740 |
||
741 |
- (Float64)float64Value { |
|
742 |
Float64 retValue; |
|
743 |
[[[self coerceToDescriptorType:typeIEEE64BitFloatingPoint] data] getBytes:&retValue]; |
|
744 |
return retValue; |
|
745 |
} |
|
746 |
||
747 |
+ (id)descriptorWithLongDateTime:(LongDateTime)val { |
|
748 |
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&val length:sizeof(val)]; |
|
749 |
} |
|
750 |
||
751 |
- (LongDateTime)longDateTimeValue { |
|
752 |
LongDateTime retValue; |
|
753 |
[[[self coerceToDescriptorType:typeLongDateTime] data] getBytes:&retValue]; |
|
754 |
return retValue; |
|
755 |
} |
|
756 |
||
757 |
+ (void)jaseSetUpHandlerDict { |
|
758 |
handlerDict = [[NSMutableDictionary alloc] init]; |
|
759 |
||
760 |
// register default handlers |
|
761 |
// types are culled from AEDataModel.h and AERegistry.h |
|
762 |
||
763 |
// string -> NSStrings |
|
764 |
[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(stringWithAEDesc:) forDescriptorTypes: |
|
765 |
typeUnicodeText, typeText, typeUTF8Text, typeCString, typeChar, nil]; |
|
766 |
||
767 |
// number/bool -> NSNumber |
|
768 |
[NSAppleEventDescriptor registerConversionHandler:[NSNumber class] selector:@selector(numberWithAEDesc:) forDescriptorTypes: |
|
769 |
typeBoolean, typeTrue, typeFalse, |
|
770 |
typeSInt16, typeSInt32, typeUInt32, typeSInt64, |
|
771 |
typeIEEE32BitFloatingPoint, typeIEEE64BitFloatingPoint, type128BitFloatingPoint, nil]; |
|
772 |
||
773 |
// list -> NSArray |
|
774 |
[NSAppleEventDescriptor registerConversionHandler:[NSArray class] selector:@selector(arrayWithAEDesc:) forDescriptorTypes:typeAEList, nil]; |
|
775 |
||
776 |
// record -> NSDictionary |
|
777 |
[NSAppleEventDescriptor registerConversionHandler:[NSDictionary class] selector:@selector(dictionaryWithAEDesc:) forDescriptorTypes:typeAERecord, nil]; |
|
778 |
||
779 |
// date -> NSDate |
|
780 |
[NSAppleEventDescriptor registerConversionHandler:[NSDate class] selector:@selector(dateWithAEDesc:) forDescriptorTypes:typeLongDateTime, nil]; |
|
781 |
||
782 |
// images -> NSImage |
|
783 |
[NSAppleEventDescriptor registerConversionHandler:[NSImage class] selector:@selector(imageWithAEDesc:) forDescriptorTypes: |
|
784 |
typeTIFF, typeJPEG, typeGIF, typePict, typeIconFamily, typeIconAndMask, nil]; |
|
785 |
||
786 |
// vers -> NSString |
|
787 |
[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(versionWithAEDesc:) forDescriptorTypes:typeVersion, nil]; |
|
788 |
||
789 |
// null -> NSNull |
|
790 |
[NSAppleEventDescriptor registerConversionHandler:[NSNull class] selector:@selector(nullWithAEDesc:) forDescriptorTypes:typeNull, nil]; |
|
791 |
} |
|
792 |
||
793 |
@end |