Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/macosx/native/apple/applescript/AS_NS_ConversionUtils.m
83406 views
/*1* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425//26// Most of this is adapted from Ken Ferry's KFAppleScript Additions, contributed with permission27// http://homepage.mac.com/kenferry/software.html28//2930#import "AS_NS_ConversionUtils.h"3132#import <Cocoa/Cocoa.h>33#import <Carbon/Carbon.h>343536@interface NSAppleEventDescriptor (JavaAppleScriptEngineAdditionsPrivate)3738// just returns self. This means that you can pass custom descriptors39// to -[NSAppleScript executeHandler:error:withParameters:].40- (NSAppleEventDescriptor *)aeDescriptorValue;4142// working with primitive descriptor types43+ (id)descriptorWithInt16:(SInt16)val;44- (SInt16)int16Value;45+ (id)descriptorWithUnsignedInt32:(UInt32)val;46- (UInt32)unsignedInt32Value;47+ (id)descriptorWithFloat32:(Float32)val;48- (Float32)float32Value;49+ (id)descriptorWithFloat64:(Float64)val;50- (Float64)float64Value;51+ (id)descriptorWithLongDateTime:(LongDateTime)val;52- (LongDateTime)longDateTimeValue;535455// These are the methods for converting AS objects to objective-C objects.56// -[NSAppleEventDescriptor objCObjectValue] is the general method for converting57// AS objects to ObjC objects, and is called by -[NSAppleScript executeHandler:error:withParameters:].58// It does no work itself. It finds a handler based on the type of the descriptor and lets that59// handler object do the work. If there is no handler type registered for a the type of a descriptor,60// the raw descriptor is returned.61//62// You can designate a handlers for descriptor types with63// +[NSAppleEventDescriptor registerConversionHandler:selector:forDescriptorTypes:]. Please note64// that this method does _not_ retain the handler object (for now anyway). The selector should65// take a single argument, a descriptor to translate, and should return an object. An example such66// selector is @selector(dictionaryWithAEDesc:), for which the handler object would be [NSDictionary class].67//68// A number of handlers are designated by default. The methods and objects can be easily inferred (or check69// the implementation), but the automatically handled types are70// typeUnicodeText,71// typeText,72// typeUTF8Text,73// typeCString,74// typeChar,75// typeBoolean,76// typeTrue,77// typeFalse,78// typeSInt16,79// typeSInt32,80// typeUInt32,81// typeSInt64,82// typeIEEE32BitFloatingPoint,83// typeIEEE64BitFloatingPoint,84// type128BitFloatingPoint,85// typeAEList,86// typeAERecord,87// typeLongDateTime,88// typeNull.89+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ...;90+ (void) jaseSetUpHandlerDict;91@end9293// wrap the NSAppleEventDescriptor string methods94@interface NSString (JavaAppleScriptEngineAdditions)95- (NSAppleEventDescriptor *)aeDescriptorValue;96+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc;97@end9899// wrap the NSAppleEventDescriptor longDateTime methods100@interface NSDate (JavaAppleScriptEngineAdditions)101- (NSAppleEventDescriptor *)aeDescriptorValue;102+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc;103@end104105// these are fairly complicated methods, due to having to try to match up the various106// AS number types (see NSAppleEventDescriptor for the primitive number methods)107// with NSNumber variants. For complete behavior it's best to look at the implementation.108// Some notes:109// NSNumbers created with numberWithBool should be correctly translated to AS booleans and vice versa.110// NSNumbers created with large integer types may have to be translated to AS doubles,111// so be careful if checking equality (you may have to check equality within epsilon).112// Since NSNumbers can't remember if they were created with an unsigned value,113// [[NSNumber numberWithUnsignedChar:255] aeDescriptorValue] is going to get you an AS integer114// with value -1. If you really need a descriptor with an unsigned value, you'll need to do it115// manually using the primitive methods on NSAppleEventDescriptor. The resulting descriptor116// can still be passed to AS with -[NSAppleScript executeHandler:error:withParameters:].117@interface NSNumber (JavaAppleScriptEngineAdditions)118- (NSAppleEventDescriptor *)aeDescriptorValue;119+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc;120@end121122// Here we're following the behavior described in the CocoaScripting release note.123//124// NSPoint -> list of two numbers: {x, y}125// NSRange -> list of two numbers: {begin offset, end offset}126// NSRect -> list of four numbers: {left, bottom, right, top}127// NSSize -> list of two numbers: {width, height}128@interface NSValue (JavaAppleScriptEngineAdditions)129- (NSAppleEventDescriptor *)aeDescriptorValue;130@end131132// No need for ObjC -> AS conversion here, we fall through to NSObject as a collection.133// For AS -> ObjC conversion, we build an array using the primitive list methods on134// NSAppleEventDescriptor.135@interface NSArray (JavaAppleScriptEngineAdditions)136+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc;137@end138139140// Please see the CocoaScripting release note for behavior. It's kind of complicated.141//142// methods wrap the primitive record methods on NSAppleEventDescriptor.143@interface NSDictionary (JavaAppleScriptEngineAdditions)144- (NSAppleEventDescriptor *)aeDescriptorValue;145+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc;146@end147148// be aware that a null descriptor does not correspond to the 'null' keyword in149// AppleScript - it's more like nothing at all. For example, the return150// from an empty handler.151@interface NSNull (JavaAppleScriptEngineAdditions)152- (NSAppleEventDescriptor *)aeDescriptorValue;153+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc;154@end155156157@interface NSNumber (JavaAppleScriptEngineAdditionsPrivate)158+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes;159+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes;160+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes;161@end162163164@implementation NSObject (JavaAppleScriptEngineAdditions)165166- (NSAppleEventDescriptor *)aeDescriptorValue {167// collections go to lists168if (![self respondsToSelector:@selector(objectEnumerator)]) {169// encode the description as a fallback - this is pretty useless, only helpful for debugging170return [[self description] aeDescriptorValue];171}172173NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor listDescriptor];174NSEnumerator *objectEnumerator = [(id)self objectEnumerator];175176unsigned int i = 1; // apple event descriptors are 1-indexed177id currentObject;178while((currentObject = [objectEnumerator nextObject]) != nil) {179[resultDesc insertDescriptor:[currentObject aeDescriptorValue] atIndex:i++];180}181182return resultDesc;183}184185@end186187188@implementation NSArray (JavaAppleScriptEngineAdditions)189190// don't need to override aeDescriptorValue, the NSObject will treat the array as a collection191+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc {192NSAppleEventDescriptor *listDesc = [desc coerceToDescriptorType:typeAEList];193NSMutableArray *resultArray = [NSMutableArray array];194195// apple event descriptors are 1-indexed196unsigned int listCount = [listDesc numberOfItems];197unsigned int i;198for (i = 1; i <= listCount; i++) {199[resultArray addObject:[[listDesc descriptorAtIndex:i] objCObjectValue]];200}201202return resultArray;203}204205@end206207208@implementation NSDictionary (JavaAppleScriptEngineAdditions)209210- (NSAppleEventDescriptor *)aeDescriptorValue {211NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor recordDescriptor];212NSMutableArray *userFields = [NSMutableArray array];213NSArray *keys = [self allKeys];214215unsigned int keyCount = [keys count];216unsigned int i;217for (i = 0; i < keyCount; i++) {218id key = [keys objectAtIndex:i];219220if ([key isKindOfClass:[NSNumber class]]) {221[resultDesc setDescriptor:[[self objectForKey:key] aeDescriptorValue] forKeyword:[(NSNumber *)key intValue]];222} else if ([key isKindOfClass:[NSString class]]) {223[userFields addObject:key];224[userFields addObject:[self objectForKey:key]];225}226}227228if ([userFields count] > 0) {229[resultDesc setDescriptor:[userFields aeDescriptorValue] forKeyword:keyASUserRecordFields];230}231232return resultDesc;233}234235+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc {236NSAppleEventDescriptor *recDescriptor = [desc coerceToDescriptorType:typeAERecord];237NSMutableDictionary *resultDict = [NSMutableDictionary dictionary];238239// NSAppleEventDescriptor uses 1 indexing240unsigned int recordCount = [recDescriptor numberOfItems];241unsigned int recordIndex;242for (recordIndex = 1; recordIndex <= recordCount; recordIndex++) {243AEKeyword keyword = [recDescriptor keywordForDescriptorAtIndex:recordIndex];244245if(keyword == keyASUserRecordFields) {246NSAppleEventDescriptor *listDescriptor = [recDescriptor descriptorAtIndex:recordIndex];247248// NSAppleEventDescriptor uses 1 indexing249unsigned int listCount = [listDescriptor numberOfItems];250unsigned int listIndex;251for (listIndex = 1; listIndex <= listCount; listIndex += 2) {252id keyObj = [[listDescriptor descriptorAtIndex:listIndex] objCObjectValue];253id valObj = [[listDescriptor descriptorAtIndex:listIndex+1] objCObjectValue];254255[resultDict setObject:valObj forKey:keyObj];256}257} else {258id keyObj = [NSNumber numberWithInt:keyword];259id valObj = [[recDescriptor descriptorAtIndex:recordIndex] objCObjectValue];260261[resultDict setObject:valObj forKey:keyObj];262}263}264265return resultDict;266}267268@end269270271@implementation NSString (JavaAppleScriptEngineAdditions)272273- (NSAppleEventDescriptor *)aeDescriptorValue {274return [NSAppleEventDescriptor descriptorWithString:self];275}276277+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc {278return [desc stringValue];279}280281+ (NSString *)versionWithAEDesc:(NSAppleEventDescriptor *)desc {282const AEDesc *aeDesc = [desc aeDesc];283VersRec v;284AEGetDescData(aeDesc, &v, sizeof(v));285return [[[NSString alloc] initWithBytes:&v.shortVersion[1] length:StrLength(v.shortVersion) encoding:NSUTF8StringEncoding] autorelease];286}287288@end289290291@implementation NSNull (JavaAppleScriptEngineAdditions)292293- (NSAppleEventDescriptor *)aeDescriptorValue {294return [NSAppleEventDescriptor nullDescriptor];295}296297+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc {298return [NSNull null];299}300301@end302303304@implementation NSDate (JavaAppleScriptEngineAdditions)305306- (NSAppleEventDescriptor *)aeDescriptorValue {307LongDateTime ldt;308UCConvertCFAbsoluteTimeToLongDateTime(CFDateGetAbsoluteTime((CFDateRef)self), &ldt);309return [NSAppleEventDescriptor descriptorWithLongDateTime:ldt];310}311312+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc {313CFAbsoluteTime absTime;314UCConvertLongDateTimeToCFAbsoluteTime([desc longDateTimeValue], &absTime);315NSDate *resultDate = (NSDate *)CFDateCreate(NULL, absTime);316return [resultDate autorelease];317}318319@end320321322323static inline int areEqualEncodings(const char *enc1, const char *enc2) {324return (strcmp(enc1, enc2) == 0);325}326327@implementation NSNumber (JavaAppleScriptEngineAdditions)328329-(id)jaseDescriptorValueWithFloatP:(void *)float_p byteCount:(int)bytes {330float floatVal;331if (bytes < sizeof(Float32)) {332floatVal = [self floatValue];333float_p = &floatVal;334bytes = sizeof(floatVal);335}336337double doubleVal;338if (bytes > sizeof(Float64)) {339doubleVal = [self doubleValue];340float_p = &doubleVal;341bytes = sizeof(doubleVal);342}343344if (bytes == sizeof(Float32)) {345return [NSAppleEventDescriptor descriptorWithFloat32:*(Float32 *)float_p];346}347348if (bytes == sizeof(Float64)) {349return [NSAppleEventDescriptor descriptorWithFloat64:*(Float64 *)float_p];350}351352[NSException raise:NSInvalidArgumentException353format:@"Cannot create an NSAppleEventDescriptor for float with %d bytes of data.", bytes];354355return nil;356}357358-(id)jaseDescriptorValueWithSignedIntP:(void *)int_p byteCount:(int)bytes {359int intVal;360361if (bytes < sizeof(SInt16)) {362intVal = [self intValue];363int_p = &intVal;364bytes = sizeof(intVal);365}366367if (bytes == sizeof(SInt16)) {368return [NSAppleEventDescriptor descriptorWithInt16:*(SInt16 *)int_p];369}370371if (bytes == sizeof(SInt32)) {372return [NSAppleEventDescriptor descriptorWithInt32:*(SInt32 *)int_p];373}374375double val = [self doubleValue];376return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];377}378379-(id)jaseDescriptorValueWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {380unsigned int uIntVal;381382if (bytes < sizeof(UInt32)) {383uIntVal = [self unsignedIntValue];384int_p = &uIntVal;385bytes = sizeof(uIntVal);386}387388if (bytes == sizeof(UInt32)) {389return [NSAppleEventDescriptor descriptorWithUnsignedInt32:*(UInt32 *)int_p];390}391392double val = (double)[self unsignedLongLongValue];393return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];394}395396- (NSAppleEventDescriptor *)aeDescriptorValue {397// NSNumber is unfortunately complicated, because the applescript398// type we should use depends on the c type that our NSNumber corresponds to399400const char *type = [self objCType];401402// convert403if (areEqualEncodings(type, @encode(BOOL))) {404return [NSAppleEventDescriptor descriptorWithBoolean:[self boolValue]];405}406407if (areEqualEncodings(type, @encode(char))) {408char val = [self charValue];409return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];410}411412if (areEqualEncodings(type, @encode(short))) {413short val = [self shortValue];414return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];415}416417if (areEqualEncodings(type, @encode(int))) {418int val = [self intValue];419return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];420}421422if (areEqualEncodings(type, @encode(long))) {423long val = [self longValue];424return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];425}426427if (areEqualEncodings(type, @encode(long long))) {428long long val = [self longLongValue];429return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];430}431432if (areEqualEncodings(type, @encode(unsigned char))) {433unsigned char val = [self unsignedCharValue];434return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];435}436437if (areEqualEncodings(type, @encode(unsigned short))) {438unsigned short val = [self unsignedShortValue];439return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];440}441442if (areEqualEncodings(type, @encode(unsigned int))) {443unsigned int val = [self unsignedIntValue];444return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];445}446447if (areEqualEncodings(type, @encode(unsigned long))) {448unsigned long val = [self unsignedLongValue];449return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];450}451452if (areEqualEncodings(type, @encode(unsigned long long))) {453unsigned long long val = [self unsignedLongLongValue];454return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];455}456457if (areEqualEncodings(type, @encode(float))) {458float val = [self floatValue];459return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];460}461462if (areEqualEncodings(type, @encode(double))) {463double val = [self doubleValue];464return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];465}466467[NSException raise:@"jaseUnsupportedAEDescriptorConversion"468format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];469470return nil;471}472473+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc {474DescType type = [desc descriptorType];475476if ((type == typeTrue) || (type == typeFalse) || (type == typeBoolean)) {477return [NSNumber numberWithBool:[desc booleanValue]];478}479480if (type == typeSInt16) {481SInt16 val = [desc int16Value];482return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];483}484485if (type == typeSInt32) {486SInt32 val = [desc int32Value];487return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];488}489490if (type == typeUInt32) {491UInt32 val = [desc unsignedInt32Value];492return [NSNumber jaseNumberWithUnsignedIntP:&val byteCount:sizeof(val)];493}494495if (type == typeIEEE32BitFloatingPoint) {496Float32 val = [desc float32Value];497return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];498}499500if (type == typeIEEE64BitFloatingPoint) {501Float64 val = [desc float64Value];502return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];503}504505// try to coerce to 64bit floating point506desc = [desc coerceToDescriptorType:typeIEEE64BitFloatingPoint];507if (desc != nil) {508Float64 val = [desc float64Value];509return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];510}511512[NSException raise:@"jaseUnsupportedAEDescriptorConversion"513format:@"JavaAppleScriptEngineAdditions: conversion of an NSAppleEventDescriptor with objCType '%s' to an aeDescriptor is not supported.", type];514515return nil;516}517518+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes {519if (bytes == sizeof(char)) {520return [NSNumber numberWithChar:*(char *)int_p];521}522523if (bytes == sizeof(short)) {524return [NSNumber numberWithShort:*(short *)int_p];525}526527if (bytes == sizeof(int)) {528return [NSNumber numberWithInt:*(int *)int_p];529}530531if (bytes == sizeof(long)) {532return [NSNumber numberWithLong:*(long *)int_p];533}534535if (bytes == sizeof(long long)) {536return [NSNumber numberWithLongLong:*(long long *)int_p];537}538539[NSException raise:NSInvalidArgumentException540format:@"NSNumber jaseNumberWithSignedIntP:byteCount: number with %i bytes not supported.", bytes];541542return nil;543}544545+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {546if (bytes == sizeof(unsigned char)) {547return [NSNumber numberWithUnsignedChar:*(unsigned char *)int_p];548}549550if (bytes == sizeof(unsigned short)) {551return [NSNumber numberWithUnsignedShort:*(unsigned short *)int_p];552}553554if (bytes == sizeof(unsigned int)) {555return [NSNumber numberWithUnsignedInt:*(unsigned int *)int_p];556}557558if (bytes == sizeof(unsigned long)) {559return [NSNumber numberWithUnsignedLong:*(unsigned long *)int_p];560}561562if (bytes == sizeof(unsigned long long)) {563return [NSNumber numberWithUnsignedLongLong:*(unsigned long long *)int_p];564}565566[NSException raise:NSInvalidArgumentException567format:@"NSNumber numberWithUnsignedInt:byteCount: number with %i bytes not supported.", bytes];568569return nil;570}571572+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes {573if (bytes == sizeof(float)) {574return [NSNumber numberWithFloat:*(float *)float_p];575}576577if (bytes == sizeof(double)) {578return [NSNumber numberWithFloat:*(double *)float_p];579}580581[NSException raise:NSInvalidArgumentException582format:@"NSNumber numberWithFloat:byteCount: floating point number with %i bytes not supported.", bytes];583584return nil;585}586587@end588589@implementation NSValue (JavaAppleScriptEngineAdditions)590591- (NSAppleEventDescriptor *)aeDescriptorValue {592const char *type = [self objCType];593594if (areEqualEncodings(type, @encode(NSSize))) {595NSSize size = [self sizeValue];596return [[NSArray arrayWithObjects:597[NSNumber numberWithFloat:size.width],598[NSNumber numberWithFloat:size.height], nil] aeDescriptorValue];599}600601if (areEqualEncodings(type, @encode(NSPoint))) {602NSPoint point = [self pointValue];603return [[NSArray arrayWithObjects:604[NSNumber numberWithFloat:point.x],605[NSNumber numberWithFloat:point.y], nil] aeDescriptorValue];606}607608if (areEqualEncodings(type, @encode(NSRange))) {609NSRange range = [self rangeValue];610return [[NSArray arrayWithObjects:611[NSNumber numberWithUnsignedInt:range.location],612[NSNumber numberWithUnsignedInt:range.location + range.length], nil] aeDescriptorValue];613}614615if (areEqualEncodings(type, @encode(NSRect))) {616NSRect rect = [self rectValue];617return [[NSArray arrayWithObjects:618[NSNumber numberWithFloat:rect.origin.x],619[NSNumber numberWithFloat:rect.origin.y],620[NSNumber numberWithFloat:rect.origin.x + rect.size.width],621[NSNumber numberWithFloat:rect.origin.y + rect.size.height], nil] aeDescriptorValue];622}623624[NSException raise:@"jaseUnsupportedAEDescriptorConversion"625format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];626627return nil;628}629630@end631632633@implementation NSImage (JavaAppleScriptEngineAdditions)634635- (NSAppleEventDescriptor *)aeDescriptorValue {636NSData *data = [self TIFFRepresentation];637return [NSAppleEventDescriptor descriptorWithDescriptorType:typeTIFF data:data];638}639640+ (NSImage *)imageWithAEDesc:(NSAppleEventDescriptor *)desc {641const AEDesc *d = [desc aeDesc];642NSMutableData *data = [NSMutableData dataWithLength:AEGetDescDataSize(d)];643AEGetDescData(d, [data mutableBytes], [data length]);644return [[[NSImage alloc] initWithData:data] autorelease];645}646647@end648649650651@implementation NSAppleEventDescriptor (JavaAppleScriptEngineAdditions)652653// we're going to leak this. It doesn't matter much for running apps, but654// for developers it might be nice to try to dispose of it (so it would not clutter the655// output when testing for leaks)656static NSMutableDictionary *handlerDict = nil;657658- (id)objCObjectValue {659if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];660661id returnObj;662DescType type = [self descriptorType];663NSInvocation *handlerInvocation = [handlerDict objectForKey:[NSValue valueWithBytes:&type objCType:@encode(DescType)]];664if (handlerInvocation == nil) {665if (type == typeType) {666DescType subType;667AEGetDescData([self aeDesc], &subType, sizeof(subType));668if (subType == typeNull) return [NSNull null];669}670// return raw apple event descriptor if no handler is registered671returnObj = self;672} else {673[handlerInvocation setArgument:&self atIndex:2];674[handlerInvocation invoke];675[handlerInvocation getReturnValue:&returnObj];676}677678return returnObj;679}680681// FIXME - error checking, non nil handler682+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ... {683if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];684685NSInvocation *handlerInvocation = [NSInvocation invocationWithMethodSignature:[anObject methodSignatureForSelector:aSelector]];686[handlerInvocation setTarget:anObject];687[handlerInvocation setSelector:aSelector];688689DescType aType = firstType;690va_list typesList;691va_start(typesList, firstType);692do {693NSValue *type = [NSValue valueWithBytes:&aType objCType:@encode(DescType)];694[handlerDict setObject:handlerInvocation forKey:type];695} while((aType = va_arg(typesList, DescType)) != 0);696va_end(typesList);697}698699700- (NSAppleEventDescriptor *)aeDescriptorValue {701return self;702}703704+ (id)descriptorWithInt16:(SInt16)val {705return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt16 bytes:&val length:sizeof(val)];706}707708- (SInt16)int16Value {709SInt16 retValue;710[[[self coerceToDescriptorType:typeSInt16] data] getBytes:&retValue];711return retValue;712}713714+ (id)descriptorWithUnsignedInt32:(UInt32)val {715return [NSAppleEventDescriptor descriptorWithDescriptorType:typeUInt32 bytes:&val length:sizeof(val)];716}717718- (UInt32)unsignedInt32Value {719UInt32 retValue;720[[[self coerceToDescriptorType:typeUInt32] data] getBytes:&retValue];721return retValue;722}723724725+ (id)descriptorWithFloat32:(Float32)val {726return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE32BitFloatingPoint bytes:&val length:sizeof(val)];727}728729- (Float32)float32Value {730Float32 retValue;731[[[self coerceToDescriptorType:typeIEEE32BitFloatingPoint] data] getBytes:&retValue];732return retValue;733}734735736+ (id)descriptorWithFloat64:(Float64)val {737return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&val length:sizeof(val)];738}739740- (Float64)float64Value {741Float64 retValue;742[[[self coerceToDescriptorType:typeIEEE64BitFloatingPoint] data] getBytes:&retValue];743return retValue;744}745746+ (id)descriptorWithLongDateTime:(LongDateTime)val {747return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&val length:sizeof(val)];748}749750- (LongDateTime)longDateTimeValue {751LongDateTime retValue;752[[[self coerceToDescriptorType:typeLongDateTime] data] getBytes:&retValue];753return retValue;754}755756+ (void)jaseSetUpHandlerDict {757handlerDict = [[NSMutableDictionary alloc] init];758759// register default handlers760// types are culled from AEDataModel.h and AERegistry.h761762// string -> NSStrings763[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(stringWithAEDesc:) forDescriptorTypes:764typeUnicodeText, typeText, typeUTF8Text, typeCString, typeChar, nil];765766// number/bool -> NSNumber767[NSAppleEventDescriptor registerConversionHandler:[NSNumber class] selector:@selector(numberWithAEDesc:) forDescriptorTypes:768typeBoolean, typeTrue, typeFalse,769typeSInt16, typeSInt32, typeUInt32, typeSInt64,770typeIEEE32BitFloatingPoint, typeIEEE64BitFloatingPoint, type128BitFloatingPoint, nil];771772// list -> NSArray773[NSAppleEventDescriptor registerConversionHandler:[NSArray class] selector:@selector(arrayWithAEDesc:) forDescriptorTypes:typeAEList, nil];774775// record -> NSDictionary776[NSAppleEventDescriptor registerConversionHandler:[NSDictionary class] selector:@selector(dictionaryWithAEDesc:) forDescriptorTypes:typeAERecord, nil];777778// date -> NSDate779[NSAppleEventDescriptor registerConversionHandler:[NSDate class] selector:@selector(dateWithAEDesc:) forDescriptorTypes:typeLongDateTime, nil];780781// images -> NSImage782[NSAppleEventDescriptor registerConversionHandler:[NSImage class] selector:@selector(imageWithAEDesc:) forDescriptorTypes:783typeTIFF, typeJPEG, typeGIF, typePict, typeIconFamily, typeIconAndMask, nil];784785// vers -> NSString786[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(versionWithAEDesc:) forDescriptorTypes:typeVersion, nil];787788// null -> NSNull789[NSAppleEventDescriptor registerConversionHandler:[NSNull class] selector:@selector(nullWithAEDesc:) forDescriptorTypes:typeNull, nil];790}791792@end793794795