B.1. Pure Raw Apple Events
If you're a Carbon programmer, you can construct a raw Apple event yourself, directly, in code. A number of other languages, such as Objective-C/Cocoa and REALbasic , give you the wherewithal to do the same thing in a possibly more convenient form. Still, no matter how you slice it, building a raw Apple event is a lot of work, and because every Apple event is different, this approach is not particularly general or flexible. You can compensate by developing libraries of wrapper functions, and Apple provides such libraries (such as the MoreAppleEvents sample code available at the developer web site), but it's still a fairly unpleasant procedure.
Here's some code for generating and sending our model events in Objective-C/Cocoa. Actually it's blended with C/Carbon, because Objective-C, curiously, although it provides some fairly convenient ways to construct the pieces of an Apple event, provides no way to send the event once it's been constructed. Also it's a lot more convenient to construct an object specifier in Carbon than in pure Cocoa. For simplicity, issue of memory management and error checking are ignored:
[[NSWorkspace sharedWorkspace] launchApplication:@"BBEdit"]; NSAppleEventDescriptor* bbedit = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplicationBundleID data:[@"com.barebones.bbedit" dataUsingEncoding:NSUTF8StringEncoding]]; NSAppleEventDescriptor* ae = [NSAppleEventDescriptor appleEventWithEventClass:'core' eventID:'crel' targetDescriptor:bbedit returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [ae setParamDescriptor:[NSAppleEventDescriptor descriptorWithTypeCode:'docu'] forKeyword:'kocl']; AESendMessage([ae aeDesc], NULL, kAENoReply | kAENeverInteract, kAEDefaultTimeout); ae = [NSAppleEventDescriptor appleEventWithEventClass:'core' eventID:'setd' targetDescriptor:bbedit returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [ae setParamDescriptor: [NSAppleEventDescriptor descriptorWithString:@"Hello, world!"] forKeyword:'data']; AEDesc docu1; CreateObjSpecifier('docu', [[NSAppleEventDescriptor nullDescriptor] aeDesc], formAbsolutePosition, [[NSAppleEventDescriptor descriptorWithInt32:1] aeDesc], YES, &docu1); AEDesc allText; CreateObjSpecifier('ctxt', &docu1, formAbsolutePosition, [[NSAppleEventDescriptor descriptorWithDescriptorType: 'abso' bytes:"all " length:4] aeDesc], YES, &allText); NSAppleEventDescriptor* allTextDesc = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&allText]; [ae setParamDescriptor:allTextDesc forKeyword:keyDirectObject]; AESendMessage([ae aeDesc], NULL, kAENoReply | kAENeverInteract, kAEDefaultTimeout);
First we make sure that BBEdit is running. Then we start forming our Apple events. An Apple event is composed of Apple event descriptors, and is itself an Apple event descriptor. Since we're going to be targeting BBEdit, we first form a target descriptor specifying BBEdit. Then we build a "make new" Apple event targeting BBEdit, set its parameter with the four-letter code for "document," and send it. Next we form a "set" Apple event. Filling in the "data" parameter (what we're going to set something to) is easy enough, but filling in the direct parameter is more involved, because this is an object specifier. We form the object specifier in two stages, working from the outside in: first we make an object specifier for "document 1," then we make a second object specifier for "[every] text of" and link it to the first object specifier. We shove the specifier into our Apple event and send it.
For more information about sending raw Apple events with Cocoa and Carbon, see the Apple documentation listed in Appendix C, along with Apple's sample code.
REALbasic's native support for forming raw Apple events remains largely incomplete, but it is sufficient for constructing and sending for the model events. The code is certainly much more compact than doing the same thing in Cocoa and Carbon:
dim ae as AppleEvent dim theDoc, theText as AppleEventObjectSpecifier dim s as new shell s.execute("open -a 'BBEdit'") ae = NewAppleEvent("core","crel", "R*ch") ae.macTypeParam("kocl") = "docu" call ae.send theDoc = getIndexedObjectDescriptor("docu", nil, 1) theText = getOrdinalObjectDescriptor("ctxt",theDoc,"all ") ae = NewAppleEvent("core","setd","R*ch") ae.objectSpecifierParam("----") = theText ae.stringParam("data") = "Hello, world!" call ae.send
For more information, see the REALbasic online help, along with Chapter 31 of my book REALbasic: The Definitive Guide, 2nd ed., O'Reilly Media, 2001 (now out of print).