source: trunk/Cocoa/Pester/Source/NDAppleScript/NDAppleScriptObject.m @ 35

Last change on this file since 35 was 35, checked in by Nicholas Riley, 19 years ago

Nathan Day's NDAppleScript and related classes, somewhat modified.
Still need to commit Nathan's changes to NDResourceFork.

File size: 34.9 KB
Line 
1/*
2 *  NDAppleScriptObject.m
3 *  NDAppleScriptObjectProject
4 *
5 *  Created by nathan on Thu Nov 29 2001.
6 *  Copyright (c) 2001 Nathan Day. All rights reserved.
7 */
8
9#import "NDAppleScriptObject.h"
10#import "NSURL+NDCarbonUtilities.h"
11#import "NDResourceFork.h"
12#import "NSAppleEventDescriptor+NDAppleScriptObject.h"
13
14const short     kScriptResourceID = 128;
15const OSType    kFinderCreatorCode = 'MACS';
16const OSType    kScriptEditorCreatorCode = 'ToyS';
17const OSType    kCompiledAppleScriptTypeCode = 'osas';
18
19static OSASendUPP                               defaultSendProcPtr = NULL;
20static long                                             defaultSendProcRefCon = 0;
21static OSAActiveProcPtr         defaultActiveProcPtr = NULL;
22static long                                             defaultActiveProcRefCon = 0;
23
24void setUpToRecieveFirstEvent( NSAppleEventDescriptor * anAppleEventDescriptor );
25
26@interface NDAppleScriptObject (private)
27+ (ComponentInstance)OSAComponent;
28+ (id)objectForAEDesc:(const AEDesc *)aDesc;
29- (OSAID)compileString:(NSString *)aString modeFlags:(long)aModeFlags;
30- (ComponentInstance)OSAComponent;
31- (OSAID)loadCompiledScriptData:(NSData *)aData;
32
33- (OSAID)compiledScriptID;
34- (OSAID)scriptContextID;
35
36- (void)setAppleScriptProcedures;
37+ (void)setAppleScriptSendProcWith:(id)anObject;
38+ (void)setAppleScriptActiveProcWith:(id)anObject;
39
40@end
41
42@interface NSString (NDAEDescCreation)
43+ (id)nd_stringWithAEDesc:(const AEDesc *)aDesc;
44@end
45
46@interface NSArray (NDAEDescCreation)
47+ (id)nd_arrayWithAEDesc:(const AEDesc *)aDesc;
48@end
49
50@interface NSDictionary (NDAEDescCreation)
51+ (id)nd_dictionaryWithAEDesc:(const AEDesc *)aDesc;
52@end
53
54@interface NSData (NDAEDescCreation)
55+ (id)nd_dataWithAEDesc:(const AEDesc *)aDesc;
56@end
57
58@interface NSNumber (NDAEDescCreation)
59+ (id)nd_numberWithAEDesc:(const AEDesc *)aDesc;
60@end
61
62@interface NSURL (NDAEDescCreation)
63+ (id)nd_URLWithAEDesc:(const AEDesc *)aDesc;
64@end
65
66@interface NSAppleEventDescriptor (NDAEDescCreation)
67+ (id)nd_appleEventDescriptorWithAEDesc:(const AEDesc *)aDesc;
68- (BOOL)nd_getAEDesc:(AEDesc *)aDescPtr;
69@end
70
71@implementation NDAppleScriptObject
72
73static ComponentInstance                defaultOSAComponent = NULL;
74
75/*
76 * + compileExecuteString:
77 */
78+ (id)compileExecuteString:(NSString *) aString
79{
80    OSAID                       theResultID;
81    AEDesc              theResultDesc = { typeNull, NULL },
82        theScriptDesc = { typeNull, NULL };
83    id                          theResultObject = nil;
84
85    [self setAppleScriptSendProcWith:nil];              // we have no instance
86    [self setAppleScriptActiveProcWith:nil];
87
88    if( (AECreateDesc( typeChar, [aString cString], [aString cStringLength], &theScriptDesc) ==  noErr) && (OSACompileExecute( [self OSAComponent], &theScriptDesc, kOSANullScript, kOSAModeNull, &theResultID) ==  noErr ) )
89       {
90        if( OSACoerceToDesc( [self OSAComponent], theResultID, typeWildCard, kOSAModeNull, &theResultDesc ) == noErr )
91           {
92            if( theResultDesc.descriptorType != typeNull )
93               {
94                theResultObject = [self objectForAEDesc:&theResultDesc];
95                AEDisposeDesc( &theResultDesc );
96               }
97           }
98        AEDisposeDesc( &theScriptDesc );
99        if( theResultID != kOSANullScript )
100            OSADispose( [self OSAComponent], theResultID );
101       }
102
103    return theResultObject;
104}
105
106/*
107 * findNextComponent
108 */
109+ (Component)findNextComponent
110{
111    ComponentDescription                theReturnCompDesc;
112    static Component                    theLastComponent = NULL;
113    ComponentDescription                theComponentDesc;
114
115    theComponentDesc.componentType = kOSAComponentType;
116    theComponentDesc.componentSubType = kOSAGenericScriptingComponentSubtype;
117    theComponentDesc.componentManufacturer = 0;
118    theComponentDesc.componentFlags =  kOSASupportsCompiling | kOSASupportsGetSource
119        | kOSASupportsAECoercion | kOSASupportsAESending
120        | kOSASupportsConvenience | kOSASupportsDialects
121        | kOSASupportsEventHandling;
122
123    theComponentDesc.componentFlagsMask = theComponentDesc.componentFlags;
124
125    do
126       {
127           theLastComponent = FindNextComponent( theLastComponent, &theComponentDesc );
128       }
129    while( GetComponentInfo( theLastComponent, &theReturnCompDesc, NULL, NULL, NULL ) == noErr && theComponentDesc.componentSubType == kOSAGenericScriptingComponentSubtype );
130
131    return theLastComponent;
132}
133
134/*
135 * closeDefaultComponent
136 */
137+ (void)closeDefaultComponent
138{
139    if( defaultOSAComponent != NULL )
140        CloseComponent( defaultOSAComponent );
141}
142
143/*
144 * + appleScriptObjectWithString:
145 */
146+ (id)appleScriptObjectWithString:(NSString *) aString
147{
148    return [[[self alloc] initWithString:aString modeFlags:kOSAModeCompileIntoContext] autorelease];
149}
150
151/*
152 * + appleScriptObjectWithData:
153 */
154+ (id)appleScriptObjectWithData:(NSData *) aData
155{
156    return [[[self alloc] initWithData:aData] autorelease];
157}
158
159/*
160 * + appleScriptObjectWithPath:
161 */
162+ (id)appleScriptObjectWithContentsOfFile:(NSString *) aPath
163{
164    return [[[self alloc] initWithContentsOfFile:aPath] autorelease];
165}
166
167/*
168 * + appleScriptObjectWithURL:
169 */
170+ (id)appleScriptObjectWithContentsOfURL:(NSURL *) aURL
171{
172    return [[[self alloc] initWithContentsOfURL:aURL] autorelease];
173}
174
175
176/*
177 * - initWithString:modeFlags:
178 */
179- (id)initWithString:(NSString *)aString modeFlags:(long)aModeFlags
180{
181    return [self initWithString:aString modeFlags:aModeFlags component:NULL];
182}
183
184/*
185 * - initWithContentsOfFile:
186 */
187- (id)initWithContentsOfFile:(NSString *)aPath
188{
189    return [self initWithContentsOfFile:aPath component:NULL];
190}
191
192/*
193 * - initWithContentsOfFile:component:
194 */
195- (id)initWithContentsOfFile:(NSString *)aPath component:(Component)aComponent
196{
197    NSData *theData;
198
199    theData = [[NDResourceFork resourceForkForReadingAtPath:aPath] dataForType: kOSAScriptResourceType Id: kScriptResourceID];
200
201    if (theData != nil) {
202        self = [self initWithData: theData component: aComponent];
203    } else {
204        NSString *scriptString = [NSString stringWithContentsOfFile: aPath];
205        self = [self initWithString: scriptString modeFlags: kOSAModeCompileIntoContext component: aComponent];
206    }
207
208    return self;
209}
210
211/*
212 * initWithContentsOfURL:
213 */
214- (id)initWithContentsOfURL:(NSURL *)aURL
215{
216    return [self initWithContentsOfURL:aURL component:NULL];
217}
218
219/*
220 * - initWithContentsOfURL:
221 */
222- (id)initWithContentsOfURL:(NSURL *)aURL component:(Component)aComponent
223{
224    NSData              * theData;
225
226    theData = [[NDResourceFork resourceForkForReadingAtURL:aURL] dataForType:kOSAScriptResourceType Id:kScriptResourceID];
227
228    if( theData != nil )
229       {
230        self = [self initWithData:theData component:aComponent];
231       }
232    else
233       {
234        [self release];
235        self = nil;
236       }
237
238    return self;
239}
240
241/*
242 * - initWithAppleEventDescriptor:
243 */
244- (id)initWithAppleEventDescriptor:(NSAppleEventDescriptor *)aDescriptor
245{
246    if( [aDescriptor descriptorType] == cScript )
247       {
248        self = [self initWithData:[aDescriptor data]];
249       }
250    else
251       {
252        [self release];
253        self = nil;
254       }
255
256    return self;
257}
258
259/*
260 * - initWithData:
261 */
262- (id)initWithData:(NSData *)aData
263{
264    return [self initWithData:aData component:NULL];
265}
266
267/*
268 * - initWithString:modeFlags:component:
269 */
270- (id)initWithString:(NSString *)aString modeFlags:(long)aModeFlags component:(Component)aComponent
271{
272    if( ( self = [super init] )  )
273       {
274        if( aComponent != NULL )
275            osaComponent = OpenComponent( aComponent );
276        else
277            osaComponent = NULL;
278
279        compiledScriptID = [self compileString:aString modeFlags: aModeFlags];
280        resultingValueID = kOSANullScript;
281        executionModeFlags = kOSAModeNull;
282        osaComponent = NULL;
283
284        if( compiledScriptID == kOSANullScript )
285           {
286            [self release];
287            self = nil;
288           }
289       }
290
291    return self;
292}
293
294/*
295 * - initWithData:componet:
296 */
297- (id)initWithData:(NSData *)aData component:(Component)aComponent
298{
299    if( (self = [self init]) != nil )
300       {
301        if( aComponent != NULL )
302            osaComponent = OpenComponent( aComponent );
303        else
304            osaComponent = NULL;
305
306        compiledScriptID = [self loadCompiledScriptData:aData];
307        resultingValueID = kOSANullScript;
308        executionModeFlags = kOSAModeNull;
309        osaComponent = NULL;
310
311        if( compiledScriptID == kOSANullScript )
312           {
313            [self release];
314            self = nil;
315           }
316       }
317
318    return self;
319}
320
321/*
322 * - dealloc
323 */
324-(void)dealloc
325{
326    if( compiledScriptID != kOSANullScript )
327        OSADispose( [self OSAComponent], compiledScriptID );
328    if( resultingValueID != kOSANullScript )
329        OSADispose( [self OSAComponent], resultingValueID );
330
331    [contextAppleScriptObject release];
332    [sendAppleEventTarget release];
333    [activeTarget release];
334
335    if( osaComponent != NULL )
336       {
337        CloseComponent( osaComponent );
338       }
339    else        // clean up the default components send and active procedure
340       {
341        OSASetSendProc( [NDAppleScriptObject OSAComponent], defaultSendProcPtr, defaultSendProcRefCon );
342        OSASetActiveProc( [NDAppleScriptObject OSAComponent], defaultActiveProcPtr , defaultActiveProcRefCon );
343       }
344
345    [super dealloc];
346}
347
348/*
349 * - data
350 */
351- (NSData *)data
352{
353    NSData                              * theData;
354    OSStatus                            theError;
355    AEDesc                              theDesc = { typeNull, NULL };
356
357    theError = (OSErr)OSAStore( [self OSAComponent], compiledScriptID, typeOSAGenericStorage, kOSAModeNull, &theDesc );
358    if( noErr == theError ) {
359        theData = [NSData nd_dataWithAEDesc: &theDesc];
360        AEDisposeDesc( &theDesc );
361        return theData;
362    }
363   
364    return nil;
365}
366
367/*
368 * - execute
369 */
370- (BOOL)execute
371{
372    OSStatus            theError;
373
374    [self setAppleScriptProcedures];
375    theError = OSAExecute([self OSAComponent], compiledScriptID, [self scriptContextID], [self executionModeFlags], &resultingValueID);
376
377    return (theError == noErr);
378}
379
380/*
381 * - executeOpen:
382 */
383- (BOOL)executeOpen:(NSArray *)aParameters
384{
385    NSAppleEventDescriptor      * theEvent = nil,
386    * theEventList = nil,
387    * theTarget = nil;
388
389    theTarget = [self targetNoProcess];
390    theEventList = [NSAppleEventDescriptor aliasListDescriptorWithArray:aParameters];
391
392    if( theTarget != nil && theEventList != nil )
393       {
394        theEvent = [NSAppleEventDescriptor appleEventWithEventClass:kCoreEventClass eventID:kAEOpenDocuments targetDescriptor:theTarget returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
395
396        [theEvent setParamDescriptor:theEventList forKeyword:keyDirectObject];
397       }
398
399    return (theEvent != nil ) ? [self executeEvent:theEvent] : NO;
400}
401
402/*
403 * - executeEvent:
404 */
405- (BOOL)executeEvent:(NSAppleEventDescriptor *)anEvent
406{
407    AEDesc                              theEventDesc;
408    BOOL                                        theSuccess = NO;
409
410    if( [anEvent nd_getAEDesc:&theEventDesc] )
411       {
412        [self setAppleScriptProcedures];
413        theSuccess = OSAExecuteEvent([self OSAComponent], &theEventDesc, compiledScriptID, [self executionModeFlags], &resultingValueID) == noErr;
414        AEDisposeDesc( &theEventDesc );
415       }
416
417    return theSuccess;
418}
419
420/*
421 * - arrayOfEventIdentifier
422 */
423- (NSArray *)arrayOfEventIdentifier
424{
425    NSArray                     * theNamesArray = nil;
426    AEDescList          theNamesDescList;
427    if( OSAGetHandlerNames ( [self OSAComponent], kOSAModeNull, compiledScriptID, &theNamesDescList ) == noErr )
428       {
429        theNamesArray = [NDAppleScriptObject objectForAEDesc: &theNamesDescList];
430        AEDisposeDesc( &theNamesDescList );
431       }
432
433    return theNamesArray;
434}
435
436/*
437 * - respondsToEventClass:eventID:
438 */
439- (BOOL)respondsToEventClass:(AEEventClass)aEventClass eventID:(AEEventID)aEventID
440{
441    NSString            * theEventClass,
442    * theEventID;
443    theEventClass = [NSString stringWithCString:(char*)&aEventClass length:sizeof(aEventClass)];
444    theEventID = [NSString stringWithCString:(char*)&aEventID length:sizeof(aEventID)];
445
446    return [[self arrayOfEventIdentifier] containsObject:[theEventClass stringByAppendingString:theEventID]];
447}
448
449/*
450 * resultDescriptor
451 */
452- (NSAppleEventDescriptor *)resultAppleEventDescriptor
453{
454    AEDesc                                                                      theResultDesc = { typeNull, NULL };
455    NSAppleEventDescriptor                              * theResult = nil;
456
457    if( OSACoerceToDesc( [self OSAComponent], resultingValueID, typeWildCard, kOSAModeNull, &theResultDesc ) == noErr )
458       {
459        theResult = [NSAppleEventDescriptor descriptorWithDescriptorType:theResultDesc.descriptorType data:[NSData nd_dataWithAEDesc:&theResultDesc]];
460        AEDisposeDesc(&theResultDesc);
461       }
462
463    return theResult;
464}
465
466/*
467 * resultObject
468 */
469- (id)resultObject
470{
471    id                          theResult = nil;
472
473    if( resultingValueID != kOSANullScript )
474       {
475        AEDesc          theResultDesc = { typeNull, NULL };
476
477        if( OSACoerceToDesc( [self OSAComponent], resultingValueID, typeWildCard, kOSAModeNull, &theResultDesc ) == noErr )
478           {
479            theResult = [NDAppleScriptObject objectForAEDesc: &theResultDesc];
480            AEDisposeDesc(&theResultDesc);
481           }
482       }
483
484    return theResult;
485}
486
487/*
488 * resultData
489 */
490- (id)resultData
491{
492    id                          theResult = nil;
493
494    if( resultingValueID != kOSANullScript )
495       {
496        AEDesc          theResultDesc = { typeNull, NULL };
497
498        if( OSACoerceToDesc( [self OSAComponent], resultingValueID, typeWildCard, kOSAModeNull, &theResultDesc ) == noErr )
499           {
500            theResult = [NSData nd_dataWithAEDesc: &theResultDesc];
501            AEDisposeDesc(&theResultDesc);
502           }
503       }
504
505    return theResult;
506}
507
508/*
509 * - resultAsString
510 */
511- (NSString *)resultAsString
512{
513    AEDesc                                      theResultDesc = { typeNull, NULL };
514    NSString                                    * theResult = nil;
515
516    if( OSADisplay( [self OSAComponent], resultingValueID, typeChar, kOSAModeNull, &theResultDesc ) == noErr )
517       {
518        theResult = [NSString nd_stringWithAEDesc:&theResultDesc];
519        AEDisposeDesc(&theResultDesc);
520       }
521
522    return theResult;
523}
524
525/*
526 * - setContextAppleScriptObject:
527 */
528- (void)setContextAppleScriptObject:(NDAppleScriptObject *)anAppleScriptObject
529{
530    [contextAppleScriptObject release];
531    contextAppleScriptObject = [anAppleScriptObject retain];
532}
533
534/*
535 * - executionModeFlags
536 */
537- (long)executionModeFlags
538{
539    return executionModeFlags;
540}
541
542/*
543 * - setExecutionModeFlags:
544 */
545- (void)setExecutionModeFlags:(long)aModeFlags
546{
547    executionModeFlags = aModeFlags;
548}
549
550/*
551 * - setDefaultTarget:
552 */
553- (void)setDefaultTarget:(NSAppleEventDescriptor *)aDefaultTarget
554{
555    AEAddressDesc               theTargetDesc;
556    if( [aDefaultTarget nd_getAEDesc:(AEDesc*)&theTargetDesc] )
557       {
558        OSASetDefaultTarget( [self OSAComponent], &theTargetDesc );
559       }
560    else
561       {
562        NSLog( @"Could not set default target" );
563       }
564}
565
566/*
567 * - setDefaultTargetAsCreator:
568 */
569- (void)setDefaultTargetAsCreator:(OSType)aCreator
570{
571    NSAppleEventDescriptor      * theAppleEventDescriptor;
572
573    theAppleEventDescriptor = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplSignature data:[NSData dataWithBytes:&aCreator length:sizeof(aCreator)]];
574    [self setDefaultTarget:theAppleEventDescriptor];
575}
576
577/*
578 * - setFinderAsDefaultTarget
579 */
580- (void)setFinderAsDefaultTarget
581{
582    [self setDefaultTargetAsCreator:kFinderCreatorCode];
583}
584
585/*
586 * setAppleEventSendTarget:
587 */
588- (void)setAppleEventSendTarget:(id)aTarget
589{
590    [sendAppleEventTarget release];
591    sendAppleEventTarget = [aTarget retain];
592}
593
594/*
595 * appleEventSendTarget
596 */
597- (id)appleEventSendTarget
598{
599    return sendAppleEventTarget;
600}
601
602/*
603 * setActiveTarget:
604 */
605- (void)setActiveTarget:(id)aTarget
606{
607    [activeTarget release];
608    activeTarget = [aTarget retain];
609}
610
611/*
612 * activeTarget
613 */
614- (id)activeTarget
615{
616    return activeTarget;
617}
618
619/*
620 * sendAppleEvent:sendMode:sendPriority:timeOutInTicks:idleProc:filterProc:
621 */
622- (NSAppleEventDescriptor *)sendAppleEvent:(NSAppleEventDescriptor *)theAppleEventDescriptor sendMode:(AESendMode)aSendMode sendPriority:(AESendPriority)aSendPriority timeOutInTicks:(long)aTimeOutInTicks idleProc:(AEIdleUPP)anIdleProc filterProc:(AEFilterUPP)aFilterProc
623{
624    AppleEvent                                          theAppleEvent;
625    NSAppleEventDescriptor              * theReplyAppleEventDesc = nil;
626
627    if( [theAppleEventDescriptor nd_getAEDesc:&theAppleEvent] )
628       {
629        AppleEvent                                      theReplyAppleEvent;
630
631        if( defaultSendProcPtr != NULL )
632           {
633            setUpToRecieveFirstEvent( theAppleEventDescriptor );
634
635            if( defaultSendProcPtr( &theAppleEvent, &theReplyAppleEvent, aSendMode, aSendPriority, aTimeOutInTicks, anIdleProc, aFilterProc, defaultSendProcRefCon ) == noErr )
636               {
637                theReplyAppleEventDesc = [NSAppleEventDescriptor nd_appleEventDescriptorWithAEDesc:&theReplyAppleEvent];
638               }
639           }
640        else
641           {
642            NSLog(@"No default send procedure");
643           }
644       }
645
646    return theReplyAppleEventDesc;
647}
648
649/*
650 * appleScriptActive
651 */
652- (BOOL)appleScriptActive
653{
654    if( defaultActiveProcPtr != NULL )
655       {
656        return defaultActiveProcPtr( defaultActiveProcRefCon ) == noErr;
657       }
658    else
659       {
660        NSLog(@"No default active procedure");
661        return NO;
662       }
663}
664
665/*
666 * targetNoProcess
667 */
668- (NSAppleEventDescriptor *)targetNoProcess
669{
670    unsigned int                                theCurrentProcess = kNoProcess; //kCurrentProcess;
671
672    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber data:[NSData dataWithBytes:&theCurrentProcess length:sizeof(theCurrentProcess)]];
673}
674
675/*
676 * description
677 */
678- (NSString *)description
679{
680    AEDesc              theDesc = { typeNull, NULL };
681    NSString            * theResult = nil;
682
683    if( OSAGetSource( [self OSAComponent], compiledScriptID, typeChar, &theDesc) == noErr )
684       {
685        theResult = [NSString nd_stringWithAEDesc: &theDesc];
686        AEDisposeDesc( &theDesc );
687       }
688
689    return theResult;
690}
691
692/*
693 * writeToURL:
694 */
695- (BOOL)writeToURL:(NSURL *)aURL
696{
697    return [self writeToURL:aURL Id:kScriptResourceID];
698}
699
700/*
701 * writeToURL:Id:
702 */
703- (BOOL)writeToURL:(NSURL *)aURL Id:(short)anID
704{
705    NSData                              * theData;
706    NDResourceFork              * theResourceFork;
707    BOOL                                        theResult = NO,
708        theCanNotWriteTo = NO;
709
710    if( (theData = [self data]) )
711       {
712        if( ![[NSFileManager defaultManager] fileExistsAtPath:[aURL path] isDirectory:&theCanNotWriteTo] )
713           {
714            theCanNotWriteTo = ![[NSFileManager defaultManager] createFileAtPath:[aURL path] contents:nil attributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedLong:kScriptEditorCreatorCode], NSFileHFSCreatorCode, [NSNumber numberWithUnsignedLong:kCompiledAppleScriptTypeCode], NSFileHFSTypeCode, nil]];
715           }
716
717        if( !theCanNotWriteTo && (theResourceFork = [NDResourceFork resourceForkForWritingAtURL:aURL]) )
718            theResult = [theResourceFork addData:theData type:kOSAScriptResourceType Id:anID name:@"script"];
719       }
720
721    return theResult;
722}
723
724/*
725 * writeToFile:
726 */
727- (BOOL)writeToFile:(NSString *)aPath
728{
729    return [self writeToURL:[NSURL fileURLWithPath:aPath] Id:kScriptResourceID];
730}
731
732/*
733 * writeToFile:Id:
734 */
735- (BOOL)writeToFile:(NSString *)aPath Id:(short)anID
736{
737    return [self writeToURL:[NSURL fileURLWithPath:aPath] Id:anID];
738}
739
740@end
741
742@implementation NDAppleScriptObject (private)
743
744/*
745 * OSAComponent
746 */
747+ (ComponentInstance)OSAComponent
748{
749    if( defaultOSAComponent == NULL )
750       {
751        defaultOSAComponent = OpenDefaultComponent( kOSAComponentType, kAppleScriptSubtype );
752       }
753    return defaultOSAComponent;
754}
755
756/*
757 * + appleScriptObjectWithAEDesc:
758 */
759+ (id)appleScriptObjectWithAEDesc:(const AEDesc *)aDesc
760{
761    NSData              * theData;
762
763    theData = [NSData nd_dataWithAEDesc: aDesc];
764
765    return ( theData == nil ) ? nil : [[[self alloc] initWithData:theData] autorelease];
766}
767
768/*
769 * + objectForAEDesc:
770 */
771+ (id)objectForAEDesc:(const AEDesc *)aDesc
772{
773    id                  theResult;
774
775#if 0
776    char                *theType = (char*)&aDesc->descriptorType;
777    NSLog(@"objectForAEDesc: recieved type '%c%c%c%c'\n",theType[0],theType[1],theType[2],theType[3]);
778#endif
779
780    switch(aDesc->descriptorType)
781       {
782        case typeBoolean:                                               //      1-byte Boolean value
783        case typeShortInteger:                          //      16-bit integer
784                                  //            case typeSMInt:                                                 //      16-bit integer
785        case typeLongInteger:                           //      32-bit integer
786                                 //             case typeInteger:                                                       //      32-bit integer
787        case typeShortFloat:                                    //      SANE single
788                                 //             case typeSMFloat:                                                       //      SANE single
789        case typeFloat:                                         //      SANE double
790                             //         case typeLongFloat:                                             //      SANE double
791                             //         case typeExtended:                                              //      SANE extended
792                             //         case typeComp:                                                  //      SANE comp
793        case typeMagnitude:                                     //      unsigned 32-bit integer
794        case typeTrue:                                                  //      TRUE Boolean value
795        case typeFalse:                                         //      FALSE Boolean value
796            theResult = [NSNumber nd_numberWithAEDesc:aDesc];
797            break;
798        case typeChar:                                                  //      unterminated string
799            theResult = [NSString nd_stringWithAEDesc:aDesc];
800            break;
801        case typeAEList:                                                //      list of descriptor records
802            theResult = [NSArray nd_arrayWithAEDesc:aDesc];
803            break;
804        case typeAERecord:                                      //      list of keyword-specified
805            theResult = [NSDictionary nd_dictionaryWithAEDesc:aDesc];
806            break;
807        case typeAppleEvent:                                            //      Apple event record
808            theResult = [NSAppleEventDescriptor nd_appleEventDescriptorWithAEDesc:aDesc];
809            break;
810        case typeAlias:                                                 //      alias record
811        case typeFileURL:
812            theResult = [NSURL nd_URLWithAEDesc:aDesc];
813            break;
814            //          case typeEnumerated:                                    //      enumerated data
815            //                  break;
816        case cScript:                                                   // script data
817            theResult = [NDAppleScriptObject appleScriptObjectWithAEDesc:aDesc];
818            break;
819        case cEventIdentifier:
820            theResult = [NSString nd_stringWithAEDesc: aDesc];
821            break;
822        default:
823            theResult = [NSAppleEventDescriptor nd_appleEventDescriptorWithAEDesc:aDesc];
824            //                  theResult = [NSData nd_dataWithAEDesc: aDesc];
825            break;
826       }
827
828    return theResult;
829}
830
831/*
832 * - compileString:
833 */
834- (OSAID)compileString:(NSString *)aString modeFlags:(long)aModeFlags
835{
836    OSAID                               theCompiledScript = kOSANullScript;
837    AEDesc                      theScriptDesc = { typeNull, NULL };
838
839    if ( AECreateDesc( typeChar, [aString cString], [aString cStringLength], &theScriptDesc) == noErr )
840       {
841        OSACompile([self OSAComponent], &theScriptDesc, aModeFlags, &theCompiledScript);
842        AEDisposeDesc( &theScriptDesc );
843       }
844
845    return theCompiledScript;
846}
847
848/*
849 * OSAComponent
850 */
851- (ComponentInstance)OSAComponent
852{
853    if( osaComponent == NULL )
854       {
855        return [NDAppleScriptObject OSAComponent];
856       }
857    else
858        return osaComponent;
859}
860
861/*
862 * - loadCompiledScriptData:
863 */
864- (OSAID)loadCompiledScriptData:(NSData *)aData
865{
866    AEDesc              theScriptDesc = { typeNull, NULL };
867    OSAID                       theCompiledScript = kOSANullScript;
868
869    if( AECreateDesc( typeOSAGenericStorage, [aData bytes], [aData length], &theScriptDesc ) == noErr )
870       {
871        OSALoad([self OSAComponent], &theScriptDesc, kOSAModeCompileIntoContext, &theCompiledScript);
872        AEDisposeDesc( &theScriptDesc );
873       }
874
875    return theCompiledScript;
876}
877
878/*
879 * - compiledScriptID
880 */
881- (OSAID)compiledScriptID
882{
883    return compiledScriptID;
884}
885
886/*
887 * - scriptContextID
888 */
889- (OSAID)scriptContextID
890{
891    return ( contextAppleScriptObject ) ? [contextAppleScriptObject compiledScriptID] : kOSANullScript;
892}
893
894/*
895 * setAppleScriptProcedures
896 */
897- (void)setAppleScriptProcedures
898{
899    [NDAppleScriptObject setAppleScriptSendProcWith:self];
900    [NDAppleScriptObject setAppleScriptActiveProcWith:self];
901}
902
903/*
904 * + setAppleScriptSendProcWith:
905 */
906+ (void)setAppleScriptSendProcWith:(id)anObject
907{
908    OSErr               AppleEventSendProc( const AppleEvent *theAppleEvent, AppleEvent *reply, AESendMode sendMode, AESendPriority sendPriority, long timeOutInTicks, AEIdleUPP idleProc, AEFilterUPP filterProc, long refCon );
909
910    ComponentInstance           theComponent;
911
912    if( sizeof(long) != sizeof(id) )
913        NSAssert( sizeof(long) == sizeof(id), @"This method works by assuming type long is the same size as type id" );
914
915    // use anObjects component else use default component
916    theComponent = (anObject) ? [anObject OSAComponent] : [self OSAComponent];
917
918    /*
919     * need to save the default send proceedure as we will call it in our send proceedure
920     */
921    if( defaultSendProcPtr == NULL )
922       {
923        if( OSAGetSendProc( theComponent, &defaultSendProcPtr, &defaultSendProcRefCon) != noErr )
924           {
925            defaultSendProcPtr = NULL;
926            NSLog(@"Could not get default AppleScript send procedure");
927           }
928       }
929
930    if( OSASetSendProc( theComponent, AppleEventSendProc, (long)anObject ) != noErr )
931       {
932        NSLog(@"Could not set AppleScript send procedure");
933       }
934}
935/*
936 * function AppleEventSendProc
937 */
938OSErr AppleEventSendProc( const AppleEvent *anAppleEvent, AppleEvent *aReply, AESendMode aSendMode, AESendPriority aSendPriority, long aTimeOutInTicks, AEIdleUPP anIdleProc, AEFilterUPP aFilterProc, long aRefCon )
939{
940    NSAppleEventDescriptor              * theAppleEventDescriptor = nil,
941    * theAppleEventDescReply;
942    OSErr                                                               theError = errOSASystemError;
943    id                                                                  theSendTarget;
944
945    /*
946     * if we have an instance, it has a target and we can create a NSAppleEventDescriptor
947     */
948    if( aRefCon != nil && (theSendTarget = [(id)aRefCon appleEventSendTarget]) != nil && (theAppleEventDescriptor = [NSAppleEventDescriptor nd_appleEventDescriptorWithAEDesc:anAppleEvent]) != nil )
949       {
950        theAppleEventDescReply = [theSendTarget sendAppleEvent:theAppleEventDescriptor sendMode:aSendMode sendPriority:aSendPriority timeOutInTicks:aTimeOutInTicks idleProc:anIdleProc filterProc:aFilterProc];
951
952        if( [theAppleEventDescReply nd_getAEDesc:(AEDesc*)aReply] )
953            theError = noErr;                   // NO ERROR
954       }
955    else if( defaultSendProcPtr != NULL )
956       {
957        setUpToRecieveFirstEvent( theAppleEventDescriptor );
958
959        theError = defaultSendProcPtr( anAppleEvent, aReply, aSendMode, aSendPriority, aTimeOutInTicks, anIdleProc, aFilterProc, defaultSendProcRefCon );
960
961       }
962
963    return theError;
964}
965
966/*
967 * + setAppleScriptActiveProcWith:
968 */
969+ (void)setAppleScriptActiveProcWith:(id)anObject
970{
971    OSErr                                               AppleScriptActiveProc( long aRefCon );
972    ComponentInstance           theComponent;
973
974    // use anObjects component else use default component
975    theComponent = (anObject) ? [anObject OSAComponent] : [self OSAComponent];
976
977    /*
978     * need to save the default active proceedure as we will call it in our active proceedure
979     */
980    if( defaultActiveProcPtr == NULL )
981       {
982        if( OSAGetActiveProc(theComponent, &defaultActiveProcPtr, &defaultActiveProcRefCon ) != noErr )
983           {
984            defaultActiveProcPtr = NULL;
985            NSLog(@"Could not get default AppleScript active procedure");
986           }
987       }
988
989    if( sizeof(long) != sizeof(id) )
990        NSAssert( sizeof(long) == sizeof(id), @"This method works by assuming type long is the same size as type id" );
991
992    if( OSASetActiveProc( theComponent, AppleScriptActiveProc , (long)anObject ) != noErr )
993        NSLog(@"Could not set AppleScript active procedure.");
994}
995/*
996        * function AppleScriptActiveProc
997        */
998OSErr AppleScriptActiveProc( long aRefCon )
999{
1000    id                  theActiveTarget;
1001
1002    if( aRefCon != nil && (theActiveTarget = [(id)aRefCon activeTarget]) != nil )
1003       {
1004        return [theActiveTarget appleScriptActive] ? noErr : errOSASystemError;
1005       }
1006    else
1007       {
1008        return defaultActiveProcPtr( defaultActiveProcRefCon );
1009       }
1010}
1011
1012@end
1013
1014/*
1015 * function setUpToRecieveFirstEvent
1016 */
1017void setUpToRecieveFirstEvent( NSAppleEventDescriptor * anAppleEventDescriptor )
1018{
1019    static BOOL                                         hasFirstEventBeenSent = NO;
1020    /*
1021     * if this is the first event to current process need to send Notification for it to work
1022     */
1023    if( !hasFirstEventBeenSent && [anAppleEventDescriptor isTargetCurrentProcess] )
1024       {
1025        hasFirstEventBeenSent = YES;
1026        [[NSNotificationCenter defaultCenter] postNotificationName:NSAppleEventManagerWillProcessFirstEventNotification object:[NSAppleEventManager sharedAppleEventManager]];
1027       }
1028}
1029
1030@implementation NSString (NDAEDescCreation)
1031
1032/*
1033 * + nd_stringWithAEDesc:
1034 */
1035+ (id)nd_stringWithAEDesc:(const AEDesc *)aDesc
1036{
1037    NSData                      * theTextData;
1038
1039    theTextData = [NSData nd_dataWithAEDesc: aDesc];
1040
1041    return ( theTextData == nil ) ? nil : [[[NSString alloc]initWithData:theTextData encoding:NSMacOSRomanStringEncoding] autorelease];
1042}
1043
1044@end
1045
1046@implementation NSArray (NDAEDescCreation)
1047
1048/*
1049 * + nd_arrayWithAEDesc:
1050 */
1051+ (id)nd_arrayWithAEDesc:(const AEDesc *)aDesc
1052{
1053    SInt32                              theNumOfItems,
1054    theIndex;
1055    id                                          theInstance = nil;
1056
1057    AECountItems( aDesc, &theNumOfItems );
1058    theInstance = [NSMutableArray arrayWithCapacity:theNumOfItems];
1059
1060    for( theIndex = 1; theIndex <= theNumOfItems; theIndex++)
1061       {
1062        AEDesc          theDesc = { typeNull, NULL };
1063        AEKeyword       theAEKeyword;
1064
1065        if( AEGetNthDesc ( aDesc, theIndex, typeWildCard, &theAEKeyword, &theDesc ) == noErr )
1066           {
1067            [theInstance addObject: [NDAppleScriptObject objectForAEDesc: &theDesc]];
1068            AEDisposeDesc( &theDesc );
1069           }
1070       }
1071
1072    return theInstance;
1073}
1074
1075@end
1076
1077@implementation NSDictionary (NDAEDescCreation)
1078
1079/*
1080 * + nd_dictionaryWithAEDesc:
1081 */
1082+ (id)nd_dictionaryWithAEDesc:(const AEDesc *)aDesc
1083{
1084    id                                          theInstance = nil;
1085    AEDesc                              theListDesc = { typeNull, NULL };
1086    AEKeyword                   theAEKeyword;
1087
1088    if( AEGetNthDesc ( aDesc, 1, typeWildCard, &theAEKeyword, &theListDesc ) == noErr )
1089       {
1090        SInt32                          theNumOfItems,
1091                                                                theIndex;
1092        AECountItems( &theListDesc, &theNumOfItems );
1093        theInstance = [NSMutableDictionary dictionaryWithCapacity:theNumOfItems];
1094
1095        for( theIndex = 1; theIndex <= theNumOfItems; theIndex += 2)
1096           {
1097            AEDesc              theDesc = { typeNull, NULL },
1098            theKeyDesc = { typeNull, NULL };
1099
1100
1101            if( ( AEGetNthDesc ( &theListDesc, theIndex + 1, typeWildCard, &theAEKeyword, &theDesc ) == noErr) && ( AEGetNthDesc ( &theListDesc, theIndex, typeWildCard, &theAEKeyword, &theKeyDesc ) == noErr) )
1102               {
1103                [theInstance setObject: [NDAppleScriptObject objectForAEDesc: &theDesc] forKey:[NSString nd_stringWithAEDesc: &theKeyDesc]];
1104                AEDisposeDesc( &theDesc );
1105                AEDisposeDesc( &theKeyDesc );
1106               }
1107            else
1108               {
1109                AEDisposeDesc( &theDesc );
1110                theInstance = nil;
1111                break;
1112               }
1113           }
1114        AEDisposeDesc( &theListDesc );
1115       }
1116
1117    return theInstance;
1118}
1119
1120@end
1121
1122@implementation NSData (NDAEDescCreation)
1123
1124/*
1125 * + nd_dataWithAEDesc:
1126 */
1127+ (id)nd_dataWithAEDesc:(const AEDesc *)aDesc
1128{
1129    NSMutableData *                     theInstance;
1130
1131    theInstance = [NSMutableData dataWithLength: (unsigned int)AEGetDescDataSize(aDesc)];
1132
1133    if( AEGetDescData(aDesc, [theInstance mutableBytes], [theInstance length]) != noErr )
1134       {
1135        theInstance = nil;
1136       }
1137
1138    return theInstance;
1139}
1140
1141@end
1142
1143@implementation NSNumber (NDAEDescCreation)
1144
1145+ (id)nd_numberWithAEDesc:(const AEDesc *)aDesc
1146{
1147    id                                          theInstance = nil;
1148
1149    switch(aDesc->descriptorType)
1150       {
1151        case typeBoolean:                                               //      1-byte Boolean value
1152           {
1153               BOOL             theBoolean;
1154               if( AEGetDescData(aDesc, &theBoolean, sizeof(BOOL)) == noErr )
1155                   theInstance = [NSNumber numberWithBool:theBoolean];
1156               break;
1157           }
1158        case typeShortInteger:                          //      16-bit integer
1159                                  //            case typeSMInt:                                                 //      16-bit integer
1160           {
1161               short int                theInteger;
1162               if( AEGetDescData(aDesc, &theInteger, sizeof(short int)) == noErr )
1163                   theInstance = [NSNumber numberWithShort: theInteger];
1164               break;
1165           }
1166        case typeLongInteger:                           //      32-bit integer
1167                                 //             case typeInteger:                                                       //      32-bit integer
1168           {
1169               int              theInteger;
1170               if( AEGetDescData(aDesc, &theInteger, sizeof(int)) == noErr )
1171                   theInstance = [NSNumber numberWithInt: theInteger];
1172               break;
1173           }
1174        case typeShortFloat:                                    //      SANE single
1175                                 //             case typeSMFloat:                                                       //      SANE single
1176           {
1177               float            theFloat;
1178               if( AEGetDescData(aDesc, &theFloat, sizeof(float)) == noErr )
1179                   theInstance = [NSNumber numberWithFloat: theFloat];
1180               break;
1181           }
1182        case typeFloat:                                         //      SANE double
1183                             //         case typeLongFloat:                                             //      SANE double
1184           {
1185               double theFloat;
1186               if( AEGetDescData(aDesc, &theFloat, sizeof(double)) == noErr )
1187                   theInstance = [NSNumber numberWithDouble: theFloat];
1188               break;
1189           }
1190            //          case typeExtended:                                              //      SANE extended
1191            //                  break;
1192            //          case typeComp:                                                  //      SANE comp
1193            //                  break;
1194        case typeMagnitude:                                     //      unsigned 32-bit integer
1195           {
1196               unsigned int             theInteger;
1197               if( AEGetDescData(aDesc, &theInteger, sizeof(unsigned int)) == noErr )
1198                   theInstance = [NSNumber numberWithUnsignedInt: theInteger];
1199               break;
1200           }
1201        case typeTrue:                                                  //      TRUE Boolean value
1202            theInstance = [NSNumber numberWithBool:YES];
1203            break;
1204        case typeFalse:                                         //      FALSE Boolean value
1205            theInstance = [NSNumber numberWithBool:NO];
1206            break;
1207        default:
1208            theInstance = nil;
1209            break;
1210       }
1211
1212    return theInstance;
1213}
1214
1215@end
1216
1217@implementation NSURL (NDAEDescCreation)
1218
1219/*
1220 * + nd_URLWithAEDesc:
1221 */
1222+ (id)nd_URLWithAEDesc:(const AEDesc *)aDesc
1223{
1224    unsigned int        theSize;
1225    id                                  theURL = nil;
1226    OSAError                    theError;
1227
1228    theSize = (unsigned int)AEGetDescDataSize(aDesc);
1229
1230    switch(aDesc->descriptorType)
1231       {
1232        case typeAlias:                                                 //      alias record
1233           {
1234               Handle                   theAliasHandle;
1235               FSRef                            theTarget;
1236               Boolean                  theWasChanged;
1237
1238               theAliasHandle = NewHandle( theSize );
1239               HLock(theAliasHandle);
1240               theError = AEGetDescData(aDesc, *theAliasHandle, theSize);
1241               HUnlock(theAliasHandle);
1242               if( theError == noErr  && FSResolveAlias( NULL, (AliasHandle)theAliasHandle, &theTarget, &theWasChanged ) == noErr )
1243                  {
1244                   theURL = [NSURL URLWithFSRef:&theTarget];
1245                  }
1246
1247               DisposeHandle(theAliasHandle);
1248               break;
1249           }
1250        case typeFileURL:                                       // ???          NOT IMPLEMENTED YET
1251            NSLog(@"NOT IMPLEMENTED YET: Attempt to create a NSURL from 'typeFileURL' AEDesc" );
1252            break;
1253       }
1254
1255    return theURL;
1256}
1257
1258@end
1259
1260@implementation NSAppleEventDescriptor (NDAEDescCreation)
1261+ (id)nd_appleEventDescriptorWithAEDesc:(const AEDesc *)aDesc
1262{
1263    return [self descriptorWithDescriptorType:aDesc->descriptorType data:[NSData nd_dataWithAEDesc:aDesc]];
1264}
1265
1266- (BOOL)nd_getAEDesc:(AEDesc *)aDescPtr
1267{
1268    NSData              * theData;
1269
1270    theData = [self data];
1271    return AECreateDesc( [self descriptorType], [theData bytes], [theData length], aDescPtr ) == noErr;
1272}
1273@end
Note: See TracBrowser for help on using the repository browser.