home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / frntsdk1.cpt / Frontier SDK 1.0 ƒ / IAC Tools / iac.c next >
Encoding:
C/C++ Source or Header  |  1991-11-05  |  20.8 KB  |  1,003 lines

  1.  
  2.  
  3. /*⌐ Copyright 1988-1991 UserLand Software, Inc.  All Rights Reserved.*/
  4.  
  5.  
  6.  
  7. #include <iac.h>
  8. #include <processes.h>
  9. #include <GestaltEqu.h>
  10.  
  11.  
  12. /*
  13. This file contains C routines that simplify the Macintosh Apple Event Manager.
  14.  
  15. The routines are grouped into several categories:
  16.  
  17. 1. Utility routines, like IACcopystring and IACloadfromhandle. These are used
  18. locally to implement other iac.c routines.
  19.  
  20. 2. Popping parameters off an Apple event, like IACgetstringparam and IACgetshortparam.
  21. When responding to an Apple event, you'll usually call one or more of these routines
  22. to get the parameters that are associated with an IAC message. Each parameter has 
  23. a 4-character "key" associated with it, you provide the key when you're asking for
  24. the parameter. If there's an error popping the parameter, the iac.c routines will
  25. automatically return an error to the Apple event caller, all you have to do is check
  26. the returned boolean and pop out of your handler.
  27.  
  28. 3. Returning a value from an Apple event call, routines like IACreturnstring and 
  29. IACreturnerror.
  30.  
  31. 4. Miscellaneous routines that defy categorization -- including IACinstallhandler,
  32. IACwaitroutine and IACinit.
  33.  
  34. Change Notes --
  35.  
  36. 10/26/91 DW: the routines that get params from an incoming event have been
  37. enhanced to return an error number and error string to the caller if we weren't
  38. able to get the requested parameter, or if it wasn't possible to coerce the
  39. parameter to the type desired by the caller. see IACparamerror for details.
  40.  
  41. 11/5/91 DW: add IACnothandlederror -- call this when you receive a verb that
  42. you don't define. this is needed by the Applet Toolkit and applications built
  43. on top of it.
  44. */
  45.  
  46.  
  47.  
  48.  
  49. tyIACglobals IACglobals;
  50.  
  51.  
  52.  
  53.  
  54. static void IACcopystring (void *source, void *dest) {
  55.  
  56.     /*
  57.     create a copy of source in dest.  copy the length byte and
  58.     all the characters in the source string.
  59.  
  60.     assume the strings are pascal strings, with the length byte in
  61.     the first character of the string.
  62.     */
  63.     
  64.     register char *s = source, *d = dest;
  65.     register short i, len;
  66.     
  67.     len = (short) s [0];
  68.     
  69.     for (i = 0; i <= len; i++) 
  70.         *d++ = *s++;
  71.     } /*IACcopystring*/
  72.  
  73.  
  74. static Boolean IACpushstring (void *source, void *dest) {
  75.  
  76.     /*
  77.     insert the source string at the end of the destination string.
  78.     
  79.     assume the strings are pascal strings, with the length byte in
  80.     the first character of the string.
  81.     */
  82.     
  83.     register char *s = source, *d = dest;
  84.     register short lensource = s [0];
  85.     register short lendest = d [0];
  86.     register short newlen = lensource + lendest;
  87.     
  88.     if (newlen > 255)
  89.         return (false);
  90.         
  91.     d [0] = (char) newlen;
  92.     
  93.     d += (char) lendest + 1; /*point at the position we're copying into*/
  94.     
  95.     s++; /*point at 1st char after length byte*/
  96.     
  97.     while (lensource--) 
  98.         *d++ = *s++;
  99.     
  100.     return (true);
  101.     } /*IACpushstring*/
  102.     
  103.     
  104. pascal Boolean IACstringtotext (s, htext) Str255 s; Handle *htext; {
  105.     
  106.     register long len;
  107.     register Handle h;
  108.     
  109.     len = s [0];
  110.     
  111.     h = NewHandle (len);
  112.     
  113.     if (h == nil)
  114.         return (false);
  115.         
  116.     BlockMove (&s [1], *h, len);
  117.     
  118.     *htext = h;
  119.     
  120.     return (true);
  121.     } /*IACstringtotext*/
  122.     
  123.     
  124. pascal Boolean IACtexttostring (htext, s) Handle htext; Str255 s; {
  125.     
  126.     long len;
  127.     
  128.     len = GetHandleSize (htext);
  129.     
  130.     if (len > 255)
  131.         len = 255;
  132.         
  133.     BlockMove (*htext, &s [1], len);
  134.     
  135.     s [0] = (char) len;
  136.     
  137.     return (true);
  138.     } /*IACtexttostring*/
  139.     
  140.     
  141. static Boolean IACloadfromhandle (hload, ixload, ctload, pdata) Handle hload; long *ixload, ctload; void *pdata; {
  142.     
  143.     /*
  144.     copy the next ctload bytes from hload into pdata and increment the index.
  145.     
  146.     return false if there aren't enough bytes.
  147.     
  148.     start ixload at 0.
  149.     */
  150.     
  151.     register Handle h = hload;
  152.     register long ct = ctload;
  153.     register long ix = *ixload;
  154.     
  155.     if ((ix + ct) > GetHandleSize (h)) /*asked for more bytes than there are*/
  156.         return (false); 
  157.     
  158.     BlockMove (*h + ix, pdata, ct); /*copy out of the handle*/
  159.     
  160.     *ixload = ix + ct; /*increment the index into the handle*/
  161.     
  162.     return (true);
  163.     } /*IACloadfromhandle*/
  164.  
  165.  
  166. pascal Boolean IAChaveappleevents () {
  167.  
  168.     /*
  169.     return true if Apple events are available.
  170.     */
  171.     
  172.     long gestaltAppleEventsPresent;
  173.     
  174.     if (Gestalt (gestaltAppleEventsAttr, &gestaltAppleEventsPresent) != noErr)
  175.         return (false);
  176.     
  177.     return (gestaltAppleEventsPresent != 0);
  178.     } /*IAChaveappleevents*/
  179.  
  180.  
  181. pascal Boolean IACinstallhandler (class, id, handler) AEEventClass class; AEEventID id; ProcPtr handler; {
  182.     
  183.     register OSErr errcode;
  184.     
  185.     errcode = AEInstallEventHandler (class, id, (EventHandlerProcPtr) handler, 0, false);
  186.     
  187.     return (errcode == noErr);
  188.     } /*AEinstallhandler*/
  189.  
  190.  
  191. pascal Boolean IACinstallcoercionhandler (fromtype, totype, handler) DescType fromtype, totype; ProcPtr handler; {
  192.     
  193.     register OSErr errcode;
  194.     
  195.     errcode = AEInstallCoercionHandler (fromtype, totype, handler, (long) 0, false, false);
  196.  
  197.     return (errcode == noErr);
  198.     } /*IACinstallcoercionhandler*/
  199.  
  200.  
  201. pascal Boolean IACnewverb (receiver, verbclass, verbtoken, event) OSType receiver, verbtoken, verbclass; AppleEvent *event; {
  202.  
  203.     /*
  204.     create a new AppleEvent record addressed to the recipient, of the indicated class,
  205.     with the indicated token identifier. return true if it worked, false otherwise.
  206.     */
  207.     
  208.     AEAddressDesc adr; 
  209.     OSErr errcode;
  210.     
  211.     AECreateDesc (typeApplSignature, (Ptr) &receiver, sizeof (receiver), &adr);
  212.     
  213.     errcode = AECreateAppleEvent (verbclass, verbtoken, &adr, kAutoGenerateReturnID, kAnyTransactionID, event);
  214.     
  215.     AEDisposeDesc (&adr);
  216.     
  217.     return (errcode == noErr);
  218.     } /*IACnewverb*/
  219.  
  220.  
  221. static Boolean IACbreakembrace (void) {
  222.     
  223.     /*
  224.     return true if the user is holding down the cmd, option and shift keys.
  225.     */
  226.     
  227.     register Ptr p;
  228.     KeyMap keys;
  229.     
  230.     GetKeys (&keys);
  231.     
  232.     p = (Ptr) keys; 
  233.     
  234.     return (BitTst (p, 63) && BitTst (p, 48) && BitTst (p, 61));
  235.     } /*IACbreakembrace*/
  236.  
  237.  
  238. pascal short IACwaitroutine (ev, sleep, mousergn) EventRecord *ev; long *sleep; RgnHandle *mousergn; {
  239.     
  240.     /*
  241.     called by the AppleEvent manager during AESend to give the user a chance to 
  242.     break out of a wait loop.
  243.     */
  244.     
  245.     if (IACbreakembrace ()) /*user holding down cmd, option and shift keys*/
  246.         return (-1); /*stop waiting*/
  247.     
  248.     return (0); /*keep waiting*/
  249.     } /*IACwaitroutine*/
  250.     
  251.  
  252. pascal Boolean IACsendverb (event, reply) AppleEvent *event, *reply; {
  253.  
  254.     /*
  255.     caller must dispose of the reply.
  256.     */
  257.  
  258.     register OSErr ec;
  259.     long mode;
  260.     
  261.     mode = kAEWaitReply + kAECanInteract + kAECanSwitchLayer;
  262.     
  263.     ec = AESend (
  264.         
  265.         event, reply, mode, kAEHighPriority, kNoTimeOut, 
  266.         
  267.         (ProcPtr) IACwaitroutine, nil);
  268.     
  269.     AEDisposeDesc (event);    
  270.     
  271.     return (ec == noErr);
  272.     } /*IACsendverb*/
  273.  
  274.  
  275. pascal Boolean IACdisposeverb (event) AppleEvent *event; {
  276.  
  277.     return (AEDisposeDesc (event) == noErr);
  278.     } /*IACdisposeverb*/
  279.     
  280.     
  281. pascal Boolean IACiserrorreply (errorstring) Str255 errorstring; {
  282.     
  283.     /*
  284.     return true if the reply is an error -- if so it has an 'errn' value
  285.     and an 'errs' value. if we return false, the reply is not an error.
  286.     */
  287.     
  288.     OSErr ec;
  289.     AEDesc desc;
  290.     
  291.     ec = AEGetParamDesc (IACglobals.reply, (AEKeyword) 'errn', 'shor', &desc);
  292.     
  293.     if (ec != noErr) /*the reply isn't an error*/
  294.         return (false);
  295.  
  296.     AEDisposeDesc (&desc);
  297.     
  298.     ec = AEGetParamDesc (IACglobals.reply, (AEKeyword) 'errs', 's255', &desc);
  299.     
  300.     if (ec != noErr) {
  301.         
  302.         IACcopystring ((char *) "\pUnknown error.", (char *) errorstring);
  303.         
  304.         return (true);
  305.         }
  306.         
  307.     IACcopystring ((char *) *desc.dataHandle, (char *) errorstring);
  308.     
  309.     AEDisposeDesc (&desc);
  310.     
  311.     return (true); /*there was an error returned*/
  312.     } /*IACiserrorreply*/
  313.     
  314.  
  315. pascal Boolean IACpushbooleanparam (val, keyword) Boolean val; OSType keyword; {
  316.     
  317.     register OSErr ec;
  318.     
  319.     ec = AEPutParamPtr (
  320.         
  321.         IACglobals.event, (AEKeyword) keyword, typeBoolean, 
  322.         
  323.         (Ptr) &val, sizeof (short));
  324.         
  325.     return (ec == noErr);
  326.     } /*IACpushbooleanparam*/
  327.  
  328.  
  329. pascal Boolean IACpushshortparam (val, keyword) short val; OSType keyword; {
  330.     
  331.     register OSErr ec;
  332.     
  333.     ec = AEPutParamPtr (
  334.         
  335.         IACglobals.event, (AEKeyword) keyword, typeShortInteger, 
  336.         
  337.         (Ptr) &val, sizeof (short));
  338.         
  339.     return (ec == noErr);
  340.     } /*IACpushshortparam*/
  341.  
  342.  
  343. pascal Boolean IACpushlongparam (val, keyword) long val; OSType keyword; {
  344.  
  345.     register OSErr ec;
  346.     
  347.     ec = AEPutParamPtr (
  348.         
  349.         IACglobals.event, (AEKeyword) keyword, typeLongInteger, 
  350.         
  351.         (Ptr) &val, sizeof (long));
  352.     
  353.     return (ec == noErr);
  354.     } /*IACpushlongparam*/
  355.  
  356.  
  357. pascal short IACpushtextparam (val, keyword) Handle val; OSType keyword; {
  358.  
  359.     AEDesc desc;
  360.     register OSErr ec;
  361.     register long len;
  362.     
  363.     desc.descriptorType = 'TEXT';
  364.     
  365.     desc.dataHandle = val;
  366.     
  367.     ec = AEPutParamDesc (IACglobals.event, (AEKeyword) keyword, &desc);
  368.     
  369.     AEDisposeDesc (&desc);
  370.     
  371.     return (ec == noErr);
  372.     } /*IACpushtextparam*/
  373.  
  374.  
  375. pascal short IACpushbinaryparam (val, keyword) Handle val; OSType keyword; {
  376.  
  377.     AEDesc desc;
  378.     register OSErr ec;
  379.     register long len;
  380.     
  381.     desc.descriptorType = 'BINA';
  382.     
  383.     desc.dataHandle = val;
  384.     
  385.     ec = AEPutParamDesc (IACglobals.event, (AEKeyword) keyword, &desc);
  386.     
  387.     AEDisposeDesc (&desc);
  388.     
  389.     return (ec == noErr);
  390.     } /*IACpushbinaryparam*/
  391.  
  392.  
  393. pascal Boolean IACpushstringparam (val, keyword) Str255 val; OSType keyword; {
  394.     
  395.     register OSErr ec;
  396.     Handle htext;
  397.     
  398.     if (!IACstringtotext (val, &htext))
  399.         return (false);
  400.         
  401.     return (IACpushtextparam (htext, keyword));
  402.     } /*IACpushstringparam*/
  403.  
  404.  
  405. pascal Boolean IACpushCstringparam (val, keyword) Str255 val; OSType keyword; {
  406.  
  407.     register OSErr ec;
  408.     register long len = 0;
  409.     register char *p = (char *) val;
  410.     
  411.     while (*p++) len++; /*get the length of the string*/
  412.     
  413.     ec = AEPutParamPtr (
  414.         
  415.         IACglobals.event, (AEKeyword) keyword, 'Sz  ', (Ptr) &val, len + 1);
  416.     
  417.     return (ec == noErr);
  418.     } /*IACpushCstringparam*/
  419.     
  420.     
  421. pascal Boolean IACreturnerror (errn, errs) short errn; Str255 errs; {
  422.     
  423.     /*
  424.     return an error string and number in an AppleEvent.
  425.     */
  426.     
  427.     register AppleEvent *x = IACglobals.event;
  428.     register Boolean fl = false;
  429.     
  430.     IACglobals.event = IACglobals.reply; /*push params on the reply record*/
  431.     
  432.     if (IACpushstringparam (errs, keyErrorString)) {
  433.     
  434.         if (IACpushshortparam (errn, keyErrorNumber))
  435.             fl = true;
  436.         }
  437.         
  438.     IACglobals.reply = x; /*restore*/
  439.     
  440.     return (fl);
  441.     } /*IACreturnerror*/
  442.     
  443.  
  444. pascal Boolean IACreturnboolean (fl) Boolean fl; {
  445.     
  446.     register OSErr ec;
  447.  
  448.     ec = AEPutParamPtr (
  449.         
  450.         IACglobals.reply, keyDirectObject, typeBoolean, (Ptr) &fl, 
  451.         
  452.         (Size) sizeof (Boolean));
  453.         
  454.     return (ec == noErr);
  455.     } /*IACreturnboolean*/
  456.  
  457.  
  458. pascal Boolean IACreturnshort (x) short x; {
  459.     
  460.     register OSErr ec;
  461.  
  462.     ec = AEPutParamPtr (
  463.         
  464.         IACglobals.reply, keyDirectObject, typeShortInteger, (Ptr) &x, 
  465.         
  466.         (Size) sizeof (short));
  467.         
  468.     return (ec == noErr);
  469.     } /*IACreturnshort*/
  470.  
  471.  
  472. pascal Boolean IACreturnlong (x) long x; {
  473.     
  474.     register OSErr ec;
  475.  
  476.     ec = AEPutParamPtr (
  477.         
  478.         IACglobals.reply, keyDirectObject, typeLongInteger, (Ptr) &x, 
  479.         
  480.         (Size) sizeof (long));
  481.         
  482.     return (ec == noErr);
  483.     } /*IACreturnlong*/
  484.  
  485.  
  486. pascal Boolean IACreturnrect (x) Rect *x; {
  487.     
  488.     register OSErr ec;
  489.  
  490.     ec = AEPutParamPtr (
  491.         
  492.         IACglobals.reply, keyDirectObject, 'qdrt', (Ptr) x, 
  493.         
  494.         (Size) sizeof (Rect));
  495.         
  496.     return (ec == noErr);
  497.     } /*IACreturnrect*/
  498.  
  499.  
  500. pascal Boolean IACreturnpoint (x) Point *x; {
  501.     
  502.     register OSErr ec;
  503.  
  504.     ec = AEPutParamPtr (
  505.         
  506.         IACglobals.reply, keyDirectObject, 'QDpt', (Ptr) x, 
  507.         
  508.         (Size) sizeof (Point));
  509.         
  510.     return (ec == noErr);
  511.     } /*IACreturnpoint*/
  512.  
  513.  
  514. pascal Boolean IACreturnbinary (x) Handle x; {
  515.     
  516.     register AppleEvent *oldevent = IACglobals.event;
  517.     register Boolean fl = false;
  518.     
  519.     IACglobals.event = IACglobals.reply; /*push params on the reply record*/
  520.     
  521.     fl = IACpushbinaryparam (x, keyDirectObject);
  522.     
  523.     IACglobals.reply = oldevent; /*restore*/
  524.     
  525.     return (fl);
  526.     } /*IACreturnbinary*/
  527.     
  528.     
  529. pascal Boolean IACreturntext (x) Handle x; {
  530.     
  531.     register AppleEvent *oldevent = IACglobals.event;
  532.     register Boolean fl = false;
  533.     
  534.     IACglobals.event = IACglobals.reply; /*push params on the reply record*/
  535.     
  536.     fl = IACpushtextparam (x, keyDirectObject);
  537.     
  538.     IACglobals.reply = oldevent; /*restore*/
  539.     
  540.     return (fl);
  541.     } /*IACreturntext*/
  542.     
  543.     
  544. pascal Boolean IACreturnstring (x) Str255 x; {
  545.     
  546.     Handle htext;
  547.     
  548.     if (!IACstringtotext (x, &htext))
  549.         return (false);
  550.         
  551.     return (IACreturntext (htext));
  552.     } /*IACreturnstring*/
  553.  
  554.  
  555. static void IACparamerror (OSErr errn, Str255 typestring, OSType paramkey) {
  556.  
  557.     /*
  558.     build an error string that looks like:
  559.     
  560.         The 'read' verb requires a string parameter with a key of '----'
  561.     
  562.     And return it to the caller.
  563.     */
  564.     
  565.     Str255 errs;
  566.     Str255 bs;
  567.     OSType verbtoken;
  568.     
  569.     verbtoken = IACgetverbtoken ();
  570.     
  571.     IACcopystring ("\pThe '", errs);
  572.     
  573.     bs [0] = 4;
  574.     
  575.     BlockMove (&verbtoken, &bs [1], 4);
  576.     
  577.     IACpushstring (bs, errs);
  578.     
  579.     IACpushstring ("\p' verb requires a ", errs);
  580.     
  581.     IACpushstring (typestring, errs);
  582.     
  583.     IACpushstring ("\p parameter with a key of '", errs);
  584.     
  585.     bs [0] = 4;
  586.     
  587.     BlockMove (¶mkey, &bs [1], 4);
  588.     
  589.     IACpushstring (bs, errs);
  590.     
  591.     IACpushstring ("\p'", errs);
  592.     
  593.     IACreturnerror (errn, errs);
  594.     } /*IACparamerror*/
  595.     
  596.     
  597. pascal void IACnothandlederror (void) {
  598.     
  599.     /*
  600.     call this if you receive an Apple event that you are not set up to handle.
  601.     
  602.     we return the standard "event not handled" error return. you can safely 
  603.     return noErr to the Apple Event Manager.
  604.     */
  605.     
  606.     IACreturnerror (errAEEventNotHandled, "\p");
  607.     } /*IACnothandlederror*/
  608.  
  609.  
  610. pascal Boolean IACgetbooleanparam (keyword, val) OSType keyword; Boolean *val; {
  611.     
  612.     register OSErr ec;
  613.     DescType actualtype;
  614.     Size actualsize;
  615.     
  616.     ec = AEGetParamPtr (
  617.         
  618.         IACglobals.event, (AEKeyword) keyword, typeBoolean, 
  619.         
  620.         &actualtype, (Ptr) val, sizeof (Boolean), &actualsize);
  621.         
  622.     if (ec != noErr) {
  623.         
  624.         IACparamerror (ec, "\pboolean", keyword);
  625.         
  626.         return (false);
  627.         }
  628.     
  629.     return (true);
  630.     } /*IACgetbooleanparam*/
  631.     
  632.  
  633. pascal Boolean IACgetshortparam (keyword, val) OSType keyword; short *val; {
  634.     
  635.     register OSErr ec;
  636.     DescType actualtype;
  637.     Size actualsize;
  638.     
  639.     ec = AEGetParamPtr (
  640.         
  641.         IACglobals.event, (AEKeyword) keyword, typeShortInteger, 
  642.         
  643.         &actualtype, (Ptr) val, sizeof (short), &actualsize);
  644.     
  645.     if (ec != noErr) {
  646.         
  647.         IACparamerror (ec, "\pshort", keyword);
  648.         
  649.         return (false);
  650.         }
  651.     
  652.     return (true);
  653.     } /*IACgetshortparam*/
  654.     
  655.  
  656. pascal Boolean IACgetlongparam (keyword, val) OSType keyword; long *val; {
  657.     
  658.     register OSErr ec;
  659.     DescType actualtype;
  660.     Size actualsize;
  661.     
  662.     ec = AEGetParamPtr (
  663.         
  664.         IACglobals.event, (AEKeyword) keyword, typeLongInteger, 
  665.         
  666.         &actualtype, (Ptr) val, sizeof (long), &actualsize);
  667.     
  668.     if (ec != noErr) {
  669.         
  670.         IACparamerror (ec, "\plong", keyword);
  671.         
  672.         return (false);
  673.         }
  674.     
  675.     return (true);
  676.     } /*IACgetlongparam*/
  677.     
  678.  
  679. pascal Boolean IACgetCstringparam (keyword, val) OSType keyword; Str255 val; {
  680.     
  681.     DescType actualtype;
  682.     Size actualsize;
  683.     OSErr ec;
  684.     
  685.     ec = AEGetParamPtr (
  686.         
  687.         IACglobals.event, (AEKeyword) keyword, 'Sz  ', 
  688.         
  689.         &actualtype, (Ptr) val, sizeof (Str255), &actualsize);
  690.     
  691.     if (ec != noErr) {
  692.         
  693.         IACparamerror (ec, "\pstring", keyword);
  694.         
  695.         return (false);
  696.         }
  697.     
  698.     return (true);
  699.     } /*IACgetCstringparam*/
  700.     
  701.  
  702. pascal Boolean IACgetrectparam (keyword, val) OSType keyword; Rect *val; {
  703.     
  704.     register OSErr ec;
  705.     DescType actualtype;
  706.     Size actualsize;
  707.     
  708.     ec = AEGetParamPtr (
  709.         
  710.         IACglobals.event, (AEKeyword) keyword, 'qdrt', 
  711.         
  712.         &actualtype, (Ptr) val, sizeof (Rect), &actualsize);
  713.     
  714.     if (ec != noErr) {
  715.         
  716.         IACparamerror (ec, "\prectangle", keyword);
  717.         
  718.         return (false);
  719.         }
  720.     
  721.     return (true);
  722.     } /*IACgetrectparam*/
  723.     
  724.  
  725. pascal Boolean IACgetpointparam (keyword, val) OSType keyword; Point *val; {
  726.     
  727.     register OSErr ec;
  728.     DescType actualtype;
  729.     Size actualsize;
  730.     
  731.     ec = AEGetParamPtr (
  732.         
  733.         IACglobals.event, (AEKeyword) keyword, 'QDpt', 
  734.         
  735.         &actualtype, (Ptr) val, sizeof (Point), &actualsize);
  736.     
  737.     if (ec != noErr) {
  738.         
  739.         IACparamerror (ec, "\ppoint", keyword);
  740.         
  741.         return (false);
  742.         }
  743.     
  744.     return (true);
  745.     } /*IACgetpointparam*/
  746.     
  747.  
  748. pascal Boolean IACgettextparam (keyword, htext) OSType keyword; Handle *htext; {
  749.     
  750.     AEDesc result;
  751.     OSErr ec;
  752.     
  753.     ec = AEGetParamDesc (IACglobals.event, (AEKeyword) keyword, 'TEXT', &result);
  754.     
  755.     if (ec != noErr) {
  756.         
  757.         IACparamerror (ec, "\ptext", keyword);
  758.         
  759.         return (false);
  760.         }
  761.     
  762.     *htext = result.dataHandle;
  763.     
  764.     return (true);
  765.     } /*IACgettextparam*/
  766.  
  767.  
  768. pascal Boolean IACgetbinaryparam (keyword, hbinary) OSType keyword; Handle *hbinary; {
  769.     
  770.     AEDesc result;
  771.     OSErr ec;
  772.     
  773.     ec = AEGetParamDesc (IACglobals.event, (AEKeyword) keyword, 'BINA', &result);
  774.     
  775.     if (ec != noErr) {
  776.         
  777.         IACparamerror (ec, "\pbinary", keyword);
  778.         
  779.         return (false);
  780.         }
  781.     
  782.     *hbinary = result.dataHandle;
  783.     
  784.     return (true);
  785.     } /*IACgetbinaryparam*/
  786.  
  787.  
  788. pascal Boolean IACgetstringparam (keyword, val) OSType keyword; Str255 val; {
  789.     
  790.     Handle htext;
  791.     
  792.     if (!IACgettextparam (keyword, &htext))
  793.         return (false);
  794.         
  795.     IACtexttostring (htext, val);
  796.     
  797.     DisposeHandle (htext);
  798.     
  799.     return (true);
  800.     } /*IACgetstringparam*/
  801.  
  802.  
  803. static Boolean IACgetlongattr (list, key, type, pattr) AppleEvent *list; AEKeyword key; DescType type; long *pattr; {
  804.     
  805.     register OSErr ec;
  806.     Size actualsize;
  807.     
  808.     ec = AEGetAttributePtr (
  809.         
  810.         list, key, type, &type, (Ptr) pattr, sizeof (long), &actualsize);
  811.     
  812.     return (ec == noErr);
  813.     } /*IACgetlongattr*/
  814.  
  815.  
  816. pascal OSType IACgetverbtoken () {
  817.     
  818.     /*
  819.     get the id/token of a verb from an AppleEvent
  820.     */
  821.     
  822.     OSType verbtoken;
  823.     
  824.     if (!IACgetlongattr (IACglobals.event, keyEventIDAttr, typeType, (long *) &verbtoken))
  825.         verbtoken = (OSType) 0;
  826.     
  827.     return (verbtoken);
  828.     } /*IACgetverbtoken*/
  829.  
  830.  
  831. pascal OSErr IACdrivefilelist (handlespecroutine) tyFScallback handlespecroutine; {
  832.     
  833.     /*
  834.     the opendoc and printdoc required events take a list of filespecs as a 
  835.     parameter. we factor out the common code, and make it a little easier for an
  836.     application to handle these events.
  837.     
  838.     you supply a callback routine that handles a single filespec, you could
  839.     print it or open it, depending on which of the required events is being
  840.     invoked.
  841.     */
  842.  
  843.     AEDesc desc;
  844.     long ctfiles;
  845.     DescType actualtype;
  846.     long actualsize;
  847.     AEKeyword actualkeyword;
  848.     FSSpec fs;
  849.     long i;
  850.     OSErr ec;
  851.                         
  852.     ec = AEGetKeyDesc (IACglobals.event, keyDirectObject, typeAEList, &desc);
  853.     
  854.     if (ec != noErr) 
  855.         return (ec);
  856.         
  857.     ec = AECountItems (&desc, &ctfiles);
  858.     
  859.     if (ec != noErr) 
  860.         return (ec);
  861.                 
  862.     for (i = 1; i <= ctfiles; i ++) {
  863.     
  864.         ec = AEGetNthPtr (
  865.             &desc, i, typeFSS, &actualkeyword, &actualtype, 
  866.             
  867.             (Ptr) &fs, sizeof (fs), &actualsize);
  868.                             
  869.         if (ec != noErr) {
  870.         
  871.             AEDisposeDesc (&desc);
  872.             
  873.             return (ec);
  874.             }
  875.             
  876.         if (!(*handlespecroutine) (&fs))
  877.             return (-1);
  878.         } /*for*/
  879.         
  880.     return (noErr);
  881.     } /*IACdrivefilelist*/
  882.  
  883.  
  884. static pascal OSErr CoerceTargetIDToType (DescType typecode, Ptr dataptr, Size datasize, DescType totype, long refcon, AEDesc *result) {
  885.     
  886.     TargetID target;
  887.     ProcessSerialNumber psn;
  888.     ProcessInfoRec info;
  889.     Ptr addressoftype;
  890.     OSErr ec;
  891.     
  892.     BlockMove (dataptr, &target, sizeof (target));
  893.     
  894.     if (target.location.locationKindSelector == ppcNoLocation) { /*local program*/
  895.         
  896.         ec = GetProcessSerialNumberFromPortName (&target.name, &psn);
  897.         
  898.         if (ec != noErr)
  899.             return (ec);
  900.         
  901.         info.processInfoLength = (long) sizeof (info);
  902.         
  903.         info.processName = nil;
  904.         
  905.         info.processAppSpec = nil;
  906.         
  907.         ec = GetProcessInformation (&psn, &info);
  908.         
  909.         if (ec != noErr)
  910.             return (ec);
  911.             
  912.         addressoftype = (Ptr) &info.processSignature;
  913.         }
  914.         
  915.     else { /*not a local program*/
  916.         
  917.         if (target.name.portKindSelector == ppcByCreatorAndType)
  918.             addressoftype = (Ptr) &target.name.u.port.creator;
  919.         else
  920.             addressoftype = ((Ptr) &target.name.u.portTypeStr) + 1; /*kloooge*/
  921.         }
  922.         
  923.     (*result).descriptorType = typeType;
  924.     
  925.     return (PtrToHand (addressoftype, &(*result).dataHandle, 4));
  926.     } /*CoerceTargetIDToType*/
  927.     
  928.     
  929. static pascal OSErr CoercePSNToType (DescType typecode, Ptr dataptr, Size datasize, DescType totype, long refcon, AEDesc *result) {
  930.     
  931.     ProcessInfoRec info;
  932.     OSErr ec;
  933.     
  934.     info.processInfoLength = (long) sizeof (info);
  935.     
  936.     info.processName = nil;
  937.     
  938.     info.processAppSpec = nil;
  939.     
  940.     ec = GetProcessInformation ((ProcessSerialNumber *) dataptr, &info);
  941.     
  942.     if (ec != noErr)
  943.         return (ec);
  944.         
  945.     (*result).descriptorType = typeType;
  946.     
  947.     return (PtrToHand (&info.processSignature, &(*result).dataHandle, 4));
  948.     } /*CoercePSNToType*/
  949.     
  950.     
  951. pascal OSType IACgetsender () { 
  952.  
  953.     /*
  954.     get application signature from address attribute. automatically
  955.     invokes our coercion handlers.
  956.     
  957.     this is needed by the Menu Sharing Toolkit -- when the user presses
  958.     cmd-period to halt a script, the next time we get a message from the
  959.     Menu Sharing server (usually Frontier) we return an error. but we only
  960.     return the error if the call came from Frontier, we use this routine
  961.     to identify the sender of the message.
  962.     
  963.     thanks to Kevin Calhoun of Apple Computer for providing this code! 
  964.     */
  965.  
  966.     OSType sender;
  967.     Size actualsize;
  968.     DescType actualtype;
  969.     OSErr errcode;
  970.     
  971.     errcode = AEGetAttributePtr (
  972.         IACglobals.event, keyAddressAttr, typeType, &actualtype, (Ptr) &sender, 
  973.         
  974.         (long) sizeof (sender), &actualsize);
  975.  
  976.     return (sender);
  977.     } /*IACgetsender*/
  978.  
  979.         
  980. pascal Boolean IACinit () {
  981.     
  982.     /*
  983.     returns true if the machine we're running on has Apple events, and if we are
  984.     able to install our coercion handlers. it may do more in future versions.
  985.     
  986.     call this routine before using any of the other iac.c routines. disable your
  987.     Apple event support if we return false.
  988.     */
  989.     
  990.     if (!IAChaveappleevents ())
  991.         return (false);
  992.         
  993.     if (!IACinstallcoercionhandler (typeProcessSerialNumber, typeType, (ProcPtr) &CoercePSNToType))
  994.         return (false);
  995.         
  996.     if (!IACinstallcoercionhandler (typeTargetID, typeType, (ProcPtr) &CoerceTargetIDToType))
  997.         return (false);
  998.         
  999.     return (true);
  1000.     } /*IACinit*/
  1001.     
  1002.     
  1003.