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

Last change on this file since 35 was 35, checked in by Nicholas Riley, 21 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
RevLine 
[35]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.