jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AS_NS_ConversionUtils.m
changeset 34552 64889edb0043
parent 34551 24317dc1c751
parent 34546 3379a11c9fd4
child 34556 4755984f1027
equal deleted inserted replaced
34551:24317dc1c751 34552:64889edb0043
     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