1 /* |
|
2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. |
|
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 |
|