home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / online / source / c / compilers / Tickle-4.0.sit.hqx / Tickle-4.0 / src / AEvent.c < prev    next >
Text File  |  1993-11-18  |  24KB  |  788 lines

  1. /*
  2. ** This source code was written by Tim Endres
  3. ** Email: time@ice.com.
  4. ** USMail: 8840 Main Street, Whitmore Lake, MI  48189
  5. **
  6. ** Some portions of this application utilize sources
  7. ** that are copyrighted by ICE Engineering, Inc., and
  8. ** ICE Engineering retains all rights to those sources.
  9. **
  10. ** Neither ICE Engineering, Inc., nor Tim Endres, 
  11. ** warrants this source code for any reason, and neither
  12. ** party assumes any responsbility for the use of these
  13. ** sources, libraries, or applications. The user of these
  14. ** sources and binaries assumes all responsbilities for
  15. ** any resulting consequences.
  16. */
  17.  
  18. #include "tickle.h"
  19.  
  20. /* InitAEStuff checks to see if this machine has AppleEvents and 
  21. *   does our setup.
  22. *   If AppleEvents are not found, we alert and exit.
  23. *   This is also the place where all the handlers for AppleEvents we deal
  24. *   with are installed.  This includes the required AppleEvents, and the
  25. *   Edition Manager specific ones used in this app.
  26. */
  27.  
  28. #pragma segment AppleEvent
  29.  
  30. #define kMiscEventClass        'misc'
  31. #define kAEDoScript            'dosc'
  32.  
  33. pascal OSErr        AEOpenHandler();
  34. pascal OSErr        AEOpenDocHandler();
  35. pascal OSErr        AEPrintHandler();
  36. pascal OSErr        AEQuitHandler();
  37. pascal OSErr        AEDoScriptHandler();
  38.  
  39. pascal OSErr        CoerceAliasToTargetID();
  40.  
  41. struct AEinstalls
  42. {
  43.     AEEventClass        theClass;
  44.     AEEventID            theEvent;
  45.     EventHandlerProcPtr    theProc;
  46. }
  47. HandlersToInstall [] =
  48. {
  49.         /* The above are the four required AppleEvents. */
  50.     {    kCoreEventClass,        kAEOpenApplication,        AEOpenHandler            },
  51.     {    kCoreEventClass,        kAEOpenDocuments,        AEOpenDocHandler        },
  52.     {    kCoreEventClass,        kAEPrintDocuments,        AEPrintHandler            },
  53.     {    kCoreEventClass,        kAEQuitApplication,        AEQuitHandler            },
  54.     {    kMiscEventClass,        kAEDoScript,            AEDoScriptHandler        },
  55. };
  56.  
  57. struct COinstalls 
  58. {
  59.     DescType    fromType;
  60.     DescType    toType;
  61.     ProcPtr        theProc;
  62.     Boolean        isDesc;        /* will usually be FALSE, System coercion */
  63. }
  64. CoercionsToInstall[] =
  65. {
  66.     {    typeAlias,            typeTargetID,    CoerceAliasToTargetID,    false    },
  67. };
  68.  
  69.  
  70. InitAEStuff()
  71.     {
  72.     long    mylong = 0;
  73.     int        myerr = noErr;
  74.     int        i;
  75.  
  76.     /* The following series of calls installs all our AppleEvent Handlers.
  77.     ** These handlers are added to the application event handler list that 
  78.     ** the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  79.     ** and we call AEProcessEvent, the AppleEvent manager will check our
  80.     ** list of handlers and dispatch to it if there is one.
  81.     */
  82.     for (i = 0; i < ((sizeof(HandlersToInstall) / sizeof(struct AEinstalls))); i++)
  83.         {
  84.         myerr = AEInstallEventHandler(    HandlersToInstall[i].theClass,
  85.                                         HandlersToInstall[i].theEvent,
  86.                                         HandlersToInstall[i].theProc,
  87.                                         0, FALSE);
  88.         if (myerr != noErr)
  89.             {
  90.             message_alert("Error %d installing Apple Event '%4.4s' Handler.",
  91.                             myerr, &HandlersToInstall[i].theEvent);
  92.             }
  93.         }
  94.     
  95.     /* now our coercion routines */
  96.     for (i = 0; i < ((sizeof(CoercionsToInstall) / sizeof(struct COinstalls))); i++)
  97.         {
  98.         myerr = AEInstallCoercionHandler(    CoercionsToInstall[i].fromType,
  99.                                             CoercionsToInstall[i].toType,
  100.                                             CoercionsToInstall[i].theProc,
  101.                                             0, FALSE, FALSE);
  102.         if (myerr)
  103.             {
  104.             message_alert("Error %d installing coercion '%4.4s' handler.",
  105.                             myerr, &CoercionsToInstall[i].fromType);
  106.             }
  107.         }
  108.     
  109.     }
  110.  
  111.  
  112. #pragma segment AppleEvents
  113.  
  114.  
  115. void
  116. DoHighLevelEvent(myEvent)
  117.     EventRecord        *myEvent;
  118.     {
  119.     int        myerr;
  120.  
  121.     /*
  122.     ** IF
  123.     **    this is an AppleEvent, and we have a handler installed, 
  124.     **    AEProcessAppleEvent jumps to that handler 
  125.     ** ELSEIF
  126.     **    there is a system handler for this event,
  127.     **    AEProcessAppleEvent jumps to that
  128.     ** ELSE
  129.     **    return errEventNotHandled.
  130.     */
  131.     myerr = AEProcessAppleEvent(myEvent);
  132.     if ((myerr != noErr) && (myerr != userCanceledErr)
  133.             && (myerr != errAEEventNotHandled))
  134.         {
  135.         message_alert("Error #%d processing Apple Event.", myerr);
  136.         /*
  137.         ** if it was a userCanceledErr (from the quit routine) and
  138.         ** the reply has been sent from there already
  139.         ** if it's a errAEEventNotHandled, then someone sent us
  140.         ** an event we're not prepared for, that is not a reason
  141.         ** to put up a dialog.  Since anyone can send us events, then
  142.         ** we could get all kinds of stray stuff, so just ignore it.
  143.         ** you may want to check for debugging reasons
  144.         */  
  145.         }
  146.     }
  147.  
  148. Boolean
  149. MissedAnyParameters(message)
  150.     AppleEvent    *message;
  151.     {
  152.     int            myerr;
  153.     DescType    ignoredActualType;
  154.     AEKeyword    missedKeyword;
  155.     Size        ignoredActualSize;
  156.     
  157.     myerr = AEGetAttributePtr(message, keyMissedKeywordAttr, typeKeyword,
  158.                                 &ignoredActualType, (Ptr)&missedKeyword,
  159.                                 sizeof(missedKeyword), &ignoredActualSize);
  160.     
  161.     /* no error means that we found some more.*/
  162.     
  163.     if (myerr == noErr) {
  164.         /* event.message = *(long *)&ignoredActualType; */
  165.         /* event.where = *(Point *)&missedKeyword; */
  166.         message_alert("MissedAnyParameters[%d]: extra parameters...", myerr);
  167.         myerr = errAEEventNotHandled;
  168.         }
  169.     else if (myerr != errAEDescNotFound) {
  170.         /*
  171.         ** errAEDescNotFound means that there are no more parameters.
  172.         ** If we get an error code other than that, flag it.
  173.         */
  174.         message_alert("MissedAnyParameters[%d]: after AEGetAttributeDesc.", myerr);
  175.         }
  176.     
  177.     return (myerr != errAEDescNotFound);
  178.     }
  179.  
  180. /*
  181. ** This is the standard Open Application event.
  182. ** You'll get this as one of the (if not the ) first events in your application.
  183. ** So, we open up a blank document.
  184. ** You will _NOT_ get this if you were launched with an event
  185. ** (like an 'odoc' or 'pdoc' ) so do _not_ do application initialiaztion things here!
  186. ** This routine may never get called!
  187. */
  188. pascal OSErr
  189. AEOpenHandler(message, reply, refnum)
  190.     AppleEvent    *message;
  191.     AppleEvent    *reply;
  192.     long        refnum;
  193.     {
  194. #pragma unused (message, reply, refnum)
  195.  
  196.     /* Do open of default window here... */
  197.  
  198.     return noErr;
  199.     }
  200.  
  201. /*
  202. ** Open Doc, opens our documents.  Remember, this can happen at application start AND
  203. ** anytime else.  If your app is up and running and the user goes to the desktop, hilites one
  204. ** of your files, and double-clicks or selects Open from the finder File menu this event
  205. ** handler will get called. Which means you don't do any initialization of globals here, or
  206. ** anything else except open then doc.
  207. ** SO -- Do NOT assume that you are at app start time in this
  208. ** routine, or bad things will surely happen to you.
  209. */
  210.  
  211. pascal OSErr
  212. AEOpenDocHandler(message, reply, refnum)
  213.     AppleEvent    *message;
  214.     AppleEvent    *reply;
  215.     long        refnum;
  216.     {
  217.     int            i;
  218.     int            result = noErr, myerr;
  219.     AEDesc        theDesc;
  220.     FSSpec        theFSS;
  221.     long        numfiles;
  222.     AEKeyword    ignoredKeyWord;
  223.     DescType    ignoredType;
  224.     Size        ignoredSize;
  225.     extern int    tcl_feedback_output();
  226. #pragma unused (reply, refnum)
  227.  
  228.     myerr = AEGetParamDesc(message, keyDirectObject, typeAEList, &theDesc);
  229.     if (myerr != noErr)
  230.         {
  231.         result = myerr;
  232.         Feedback("GetParamDesc error %d in Open Doc", myerr);
  233.         }
  234.     if (! MissedAnyParameters(message))
  235.         {
  236.         /* Got all the parameters we need. Now, go through the direct object, */
  237.         /* see what type it is, and parse it up. */
  238.         myerr = AECountItems(&theDesc, &numfiles);
  239.         if (myerr != noErr)
  240.             {
  241.             result = myerr;
  242.             Feedback("Error %d AECountItems in Open Doc", myerr);
  243.             }
  244.         else {
  245.             for (i = 1; i <= numfiles && myerr == noErr ; ++i)
  246.                 {
  247.                 myerr = AEGetNthPtr(&theDesc, i, typeFSS, &ignoredKeyWord, &ignoredType,
  248.                                         (Ptr)&theFSS, sizeof(theFSS), &ignoredSize);
  249.                 if (myerr == noErr)
  250.                     {
  251.                     result = myerr;
  252.                     myerr = AEHandleDoc(&theFSS);
  253.                     }
  254.                 else
  255.                     {
  256.                     result = myerr;
  257.                     Feedback("Error %d AEGetNthPtr in OpenDoc", myerr);
  258.                     }
  259.                 }
  260.             }
  261.         }
  262.     
  263.     if (myerr = AEDisposeDesc(&theDesc))
  264.         {
  265.         result = myerr;
  266.         Feedback("Error %d AEDisposeDesc in Open Doc", myerr);
  267.         }
  268.  
  269.     return result;
  270.     }
  271.  
  272. pascal OSErr
  273. AEPrintHandler(message, reply, refnum)
  274.     AppleEvent    *message;
  275.     AppleEvent    *reply;
  276.     long        refnum;
  277.     {
  278. #pragma unused (message, reply, refnum)
  279.  
  280.     /*
  281.     ** No printing handler in yet, so we'll ignore this
  282.     ** the operation is functionally identical to the ODOC event,
  283.     ** with the additon of calling your print routine.
  284.     */
  285.  
  286.     message_alert("Print Document...");
  287.     return noErr;
  288.     }
  289.  
  290. /*
  291. ** Standard Quit event handler, to handle a Quit event from the Finder, for example.
  292. ** ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.
  293. ** OK, it's a few months after I wrote that comment, and I've seen a lot of code
  294. ** come through DTS that calls ExitToShell from quit handlers.  Let me explain...
  295. ** When an AppleEvent Handler is called (like this quit handler) you are ALMOST
  296. ** 100% in your application world.  A5 is right, you can call any toolbox function,
  297. ** you can call your own routines, everything _seems_ like you are in complete
  298. ** control.  Well, almost but not quite.  The routine has been dispatch to from the
  299. ** AppleEvent Manager's space, so you _must_ return to that at some point!
  300. ** Which is why you can't call ETS from here.  When you call ExitToShell from an
  301. ** AE Handler, the most likely thing that happens is the FInder quits, and your
  302. ** application keeps running.  Which ain't what you want, y'know?
  303. ** so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!!
  304. */
  305. pascal OSErr
  306. AEQuitHandler(message, reply, refnum)
  307.     AppleEvent    *message;
  308.     AppleEvent    *reply;
  309.     long        refnum;
  310.     {
  311. #pragma unused (message, reply, refnum)
  312.  
  313.     app_done = 1;
  314.     Feedback("Quit event...");
  315.     return noErr;
  316.     }
  317.  
  318. /*
  319. ** Open Doc, opens our documents.  Remember, this can happen at application start AND
  320. ** anytime else.  If your app is up and running and the user goes to the desktop, hilites one
  321. ** of your files, and double-clicks or selects Open from the finder File menu this event
  322. ** handler will get called. Which means you don't do any initialization of globals here, or
  323. ** anything else except open then doc.
  324. ** SO -- Do NOT assume that you are at app start time in this
  325. ** routine, or bad things will surely happen to you.
  326. */
  327.  
  328. pascal OSErr
  329. AEDoScriptHandler(message, reply, refnum)
  330.     AppleEvent    *message;
  331.     AppleEvent    *reply;
  332.     long        refnum;
  333.     {
  334.     int            result = noErr, myerr;
  335.     char        error_str[128];
  336.     AEDesc        theDesc;
  337.     FSSpec        theFSS;
  338.     long        length;
  339.     Handle        result_handle;
  340.     DescType    ignoredType;
  341.     Size        ignoredSize;
  342.     extern int    tcl_feedback_output();
  343. #pragma unused (reply, refnum)
  344.  
  345.     result_handle = NewHandle(0);
  346.     if (result_handle != NULL) {
  347.         myerr = AEGetParamDesc(message, keyDirectObject, typeWildCard, &theDesc);
  348.         if (myerr != noErr) {
  349.             result = myerr;
  350.             Feedback("GetParamDesc error %d in Do Script", myerr);
  351.             }
  352.         if (! MissedAnyParameters(message)) {
  353.             /* Got all the parameters we need. Now, go through the direct object, */
  354.             /* see what type it is, and parse it up. */
  355.             /* dprintf( "GOT PARM type '%4.4s' handle x%lx ; dm %lx %d  ",
  356.                         &theDesc.descriptorType, theDesc.dataHandle,
  357.                         *(theDesc.dataHandle), GetHandleSize(theDesc.dataHandle) ); */
  358.             if (theDesc.descriptorType == (DescType)'TEXT')
  359.                 {
  360.                 length = GetHandleSize(theDesc.dataHandle);
  361.                 SetHandleSize(theDesc.dataHandle, length + 1);
  362.                 if (MemError() == noErr) {
  363.                     * (*theDesc.dataHandle + length) = '\0';
  364.                     result = run_DoScript(theDesc.dataHandle, result_handle);
  365.                     length = GetHandleSize(result_handle);
  366.                     HLock(result_handle);
  367.                     myerr = AEPutParamPtr(reply, keyDirectObject, typeChar,
  368.                                             *result_handle, length);
  369.                     HUnlock(result_handle);
  370.                     }
  371.                 }
  372.             else if (theDesc.descriptorType == (DescType)'alis')
  373.                 {
  374.                 myerr = AEGetParamPtr(    message,
  375.                                         keyDirectObject, typeFSS, &ignoredType,
  376.                                         (Ptr)&theFSS, sizeof(theFSS), &ignoredSize
  377.                                         );
  378.                 if (myerr == noErr)
  379.                     {
  380.                     Feedback("AEDoScriptHandler: Execute script file '%.*s'.",
  381.                                     theFSS.name[0], &theFSS.name[1]);
  382.                     run_AE_tcl_script(&theFSS, result_handle);
  383.                     length = GetHandleSize(result_handle);
  384.                     HLock(result_handle);
  385.                     myerr = AEPutParamPtr(reply, keyDirectObject, typeChar,
  386.                                             *result_handle, length);
  387.                     HUnlock(result_handle);
  388.                     }
  389.                 else
  390.                     {
  391.                     Feedback("AEDoScriptHandler: Error #%d AEGetParamPtr(typeFSS).", myerr);
  392.                     }
  393.                 }
  394.             else
  395.                 {
  396.                 sprintf(error_str, "invalid script type '%4.4s'", &theDesc.descriptorType);
  397.                 myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  398.                                         error_str, strlen(error_str));
  399.                 }
  400.             }
  401.         else
  402.             message_alert("AEDoScriptHandler: MissedAnyParameters!!!");
  403.         
  404.         if (myerr = AEDisposeDesc(&theDesc)) {
  405.             result = myerr;
  406.             Feedback("Error %d AEDisposeDesc in Do Script.", myerr);
  407.             }
  408.         
  409.         DisposHandle(result_handle);
  410.         }
  411.     else
  412.         result = MemError();
  413.     
  414.     return result;
  415.     }
  416.  
  417. /*
  418. ** This is the 'ansr', or answer, handler.  You need this if you ever want to
  419. ** use QueueReply as an option to AESend (which you will) since the reply
  420. ** is going to be coming in through your event loop like any other
  421. ** AppleEvent.   So here it is
  422. */
  423. pascal OSErr
  424. AEAnswerHandler(message, reply, refnum)
  425.     AppleEvent    *message;
  426.     AppleEvent    *reply;
  427.     long        refnum;
  428.     {
  429.     int        myErr = noErr;
  430. #pragma unused (message, reply, refnum) 
  431.         
  432.     return noErr;
  433.     /*
  434.     ** •••• NOTE:  One thing you may want to consider, and it's a side-effect of
  435.     ** the AppleEvent manager's direct dispatching of events if you send them to yourself
  436.     ** using the kCurrentProcess Process Serial Number constant.
  437.     ** If you use kCurrentProcess, then the AppleEvent manager will directly dispatch
  438.     ** to the AppleEvent handler, the event will _not_ go through WaitNextEvent.
  439.     ** Normally, that's a very good thing.  But there is one potential problem....
  440.     ** It means that kQueueReply doesn't quite work the way you think it will when sending to
  441.     ** yourself.  The reply will _not_ be put in the event queue, instead this Answer hander
  442.     ** will be called directly.  And if you reply from the answer handler, that will dispatch right
  443.     ** back to itself.  And so on.  So be aware that Queued replies are _not_ really
  444.     ** queued when you are using kCurrentProcess!
  445.     */
  446.     }
  447.  
  448.  
  449. /*
  450. ** CoerceAliasToTargetID takes an applicaiton alias and coerces it to a process target ID
  451. ** Of course, to do this is needs to find and launch the application
  452. ** This handler uses pointers to the data, since the AppleEvent managr can handle this type
  453. ** of manipulation more efficiently than passing descs.  You can install a desc handler
  454. ** instead, if you'd like.
  455. ** I actually don't use this in this sample, but I left it in as an example
  456. ** of a coercion handler
  457. */
  458. pascal OSErr
  459. CoerceAliasToTargetID(origData, inPtr, theSize, toType, refCon, returnID)
  460.     DescType    origData;
  461.     Ptr            inPtr;
  462.     Size        theSize;
  463.     DescType    toType;
  464.     long        refCon;
  465.     AEDesc        *returnID;
  466.     {
  467. #pragma unused (origData, toType, refCon)
  468.  
  469.     int        myerr;
  470.     FSSpec    theSpec;
  471.     Boolean    changed;
  472.     Handle    theAlias;
  473.     LaunchParamBlockRec    launchThis;
  474.  
  475.     theAlias = NewHandle(theSize);
  476.     if (theAlias != NULL)
  477.         {
  478.         HLock(theAlias);
  479.         BlockMove(inPtr, (Ptr)*theAlias, theSize);
  480.         HUnlock(theAlias);
  481.         
  482.         launchThis.launchAppSpec = &theSpec;
  483.         /* the caller may have already done this, but it doesn't hurt to do it again */
  484.         myerr = ResolveAlias((FSSpec *)0, (AliasHandle)theAlias,
  485.                                 launchThis.launchAppSpec, &changed);
  486.         if (myerr != noErr)
  487.             return myerr;
  488.         
  489.         /* launch the thing */
  490.         launchThis.launchBlockID = extendedBlock;
  491.         launchThis.launchEPBLength = extendedBlockLen;
  492.         launchThis.launchFileFlags = 0;
  493.         /* launchdontswitch because we just want to use the service.  Also, it may be a */
  494.         /* background only application, so like you don't want it to come up, y'know? */
  495.         launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchDontSwitch;
  496.         launchThis.launchAppParameters = nil;
  497.         myerr = LaunchApplication(&launchThis);
  498.         if (myerr != noErr)
  499.             {
  500.             message_alert("LaunchApplication error %d.", myerr);
  501.             return myerr;
  502.             }
  503.         
  504.         /*
  505.         ** it launched.  the PSN has been stored in the launchProcessSN field,
  506.         ** now we have to make that a target
  507.         ** fill in all the details for the target
  508.         ** we'll just use the PSN to communicate
  509.         */
  510.         myerr = AECreateDesc(typeProcessSerialNumber, (Ptr)&launchThis.launchProcessSN,
  511.                                     sizeof(ProcessSerialNumber), returnID);
  512.         message_alert("CreateDesc error after launch %d.", myerr);
  513.         }
  514.     else
  515.         myerr = MemError();
  516.     
  517.     return myerr;
  518.     }
  519.  
  520.  
  521. typedef struct
  522.     {
  523.     char        name[48];        
  524.     } DirListEntry;
  525.  
  526.  
  527. AEHandleDoc(theFSS)
  528.     FSSpec        *theFSS;
  529.     {
  530.     int            result = noErr;
  531.     int            i, entries, myerr, script_type = -1, run_it = 0;
  532.     short        wdrefnum;
  533.     long        dirid;
  534.     FSSpec        myFSS;
  535.     CInfoPBRec    cpb;
  536.     FInfo        fileInfo;
  537.     char        filename[64];
  538.     DirListEntry    *list;
  539.  
  540.     if (theFSS->name[1] == 0xA5)
  541.         {
  542.         Feedback("Skipping '%.*s'...", theFSS->name[0], &theFSS->name[1]);
  543.         return noErr;
  544.         }
  545.     
  546.     cpb.hFileInfo.ioCompletion = 0;
  547.     cpb.hFileInfo.ioNamePtr = theFSS->name;
  548.     cpb.hFileInfo.ioVRefNum = theFSS->vRefNum;
  549.     cpb.hFileInfo.ioDirID = theFSS->parID;
  550.     cpb.hFileInfo.ioFDirIndex = 0;
  551.     myerr = PBGetCatInfo(&cpb, FALSE);
  552.     if (myerr != noErr)
  553.         {
  554.         Feedback("Error #%d getting CatInfo for '%.*s'.",
  555.                     myerr, theFSS->name[0], &theFSS->name[1]);
  556.         }
  557.     else if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) != 0)
  558.         {
  559.         /* DIRECTORY!!! */
  560.         Feedback("AppleEvent: Processing folder '%.*s'[%ld] with %ld items.",
  561.                     theFSS->name[0], &theFSS->name[1], cpb.dirInfo.ioDrDirID, cpb.dirInfo.ioDrNmFls);
  562.         dirid = cpb.dirInfo.ioDrDirID;
  563.         list = (DirListEntry *) NewPtr(cpb.dirInfo.ioDrNmFls * sizeof(DirListEntry));
  564.         if (list == NULL)
  565.             {
  566.             Feedback("AppleEvent: Not enough memory to process folder '%.*s'.",
  567.                         theFSS->name[0], &theFSS->name[1]);
  568.             }
  569.         else
  570.             {
  571.             for (i = 1, entries = 0 ; ; ++i)
  572.                 {
  573.                 cpb.hFileInfo.ioCompletion = 0;
  574.                 cpb.hFileInfo.ioNamePtr = filename; filename[0] = '\0';
  575.                 cpb.hFileInfo.ioVRefNum = theFSS->vRefNum;
  576.                 cpb.hFileInfo.ioDirID = dirid;
  577.                 cpb.hFileInfo.ioFDirIndex = i;
  578.                 myerr = PBGetCatInfo(&cpb, FALSE);
  579.                 if (myerr != noErr)
  580.                     {
  581.                     if (myerr != fnfErr)
  582.                         Feedback("Error #%d CatInfo '%.*s' ENTRY #%d.",
  583.                                     myerr, theFSS->name[0], &theFSS->name[1], i);
  584.                     break;
  585.                     }
  586.                 else
  587.                     {
  588.                     /*list[entries].directory = (cpb.hFileInfo.ioFlAttrib & ioDirMask) != 0;*/
  589.                     BlockMove(filename, list[entries].name, filename[0]+1);
  590.                     entries++;
  591.                     }
  592.                 }
  593.             
  594.             for (i = 0; i < entries ; ++i)
  595.                 {
  596.                 BlockMove(list[i].name, myFSS.name, list[i].name[0] + 1);
  597.                 myFSS.vRefNum = theFSS->vRefNum;
  598.                 myFSS.parID = dirid;
  599.                 AEHandleDoc(&myFSS);
  600.                 }
  601.             
  602.             DisposPtr((Ptr) list);
  603.             }
  604.         }
  605.     else
  606.         {
  607.         /* FILE */
  608.         
  609.         FSpGetFInfo(theFSS, &fileInfo);    /* make sure it's a data file */
  610.         if (fileInfo.fdType == 'TEXT')
  611.             {
  612.             if (     theFSS->name[theFSS->name[0]-3]            == '.'
  613.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 'h'
  614.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'q'
  615.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'x')
  616.                 {
  617.                 AEdecode_hqx(theFSS);
  618.                 }
  619.             else if (theFSS->name[theFSS->name[0]-1]            == '.'
  620.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'z')
  621.                 {
  622.                 AEdecompress(theFSS);
  623.                 }
  624.             else if (theFSS->name[theFSS->name[0]-2]            == '.'
  625.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'u'
  626.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'u') {
  627.                 AEuudecode(theFSS);
  628.                 }
  629.             else if (theFSS->name[theFSS->name[0]-3]            == '.'
  630.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 's'
  631.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'i'
  632.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 't') {
  633.                 AEUnStuffIt(theFSS);
  634.                 }
  635.             else if (theFSS->name[theFSS->name[0]-3]            == '.'
  636.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 't'
  637.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'a'
  638.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'r') {
  639.                 AEExtract(theFSS);
  640.                 }
  641.             else if (theFSS->name[theFSS->name[0]-2]            == '.'
  642.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'm'
  643.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'b') {
  644.                 AEUnMacBinary(theFSS);
  645.                 }
  646.             else {
  647.                 /* OK... Assume it is a script. */
  648.                 if (     theFSS->name[theFSS->name[0]-3]            == '.'
  649.                     &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 't'
  650.                     &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'c'
  651.                     &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'l')
  652.                     {
  653.                     script_type = 0; /* local script */
  654.                     run_it = 1;
  655.                     }
  656.                 else
  657.                     {
  658.                     script_type = -1; /* text window */ 
  659.                     run_it = 0;
  660.                     }
  661.                 
  662.                 Feedback("AppleEvent: %s script '%.*s'.",
  663.                             (run_it ? "Running" : "Opening"), theFSS->name[0], &theFSS->name[1]);
  664.                 
  665.                 if (run_it)
  666.                     {
  667.                     myerr = OpenWD(theFSS->vRefNum, theFSS->parID, 'MTcl', &wdrefnum);
  668.                     if (myerr == noErr)
  669.                         SetVol(NULL, wdrefnum);
  670.                     else
  671.                         Feedback("Error %d OpenWD().", myerr);
  672.                     
  673.                     run_named_tcl_script(theFSS->name, NULL, tcl_feedback_output);
  674.                     
  675.                     if (myerr == noErr)
  676.                         myerr = CloseWD(wdrefnum);
  677.                     }
  678. #ifdef TCLAPPL
  679.                 else
  680.                     {
  681.                     do_tge_file_open(theFSS, script_type);
  682.                     }
  683. #endif
  684.                 }
  685.             }
  686.         else if (fileInfo.fdType == 'TARF')
  687.             {
  688.             Feedback("AppleEvent: Extracting Tar File '%.*s'.",
  689.                         theFSS->name[0], &theFSS->name[1]);
  690.             AEExtract(theFSS);
  691.             }
  692.         else if (fileInfo.fdType == 'ZIVM')
  693.             {
  694.             Feedback("AppleEvent: Macintosh style De-Compress. Trying normal extract on '%.*s'.",
  695.                         theFSS->name[0], &theFSS->name[1]);
  696.             AEdecompress(theFSS);
  697.             }
  698.         else if (fileInfo.fdType == 'ZIVU')
  699.             {
  700.             Feedback("AppleEvent: De-Compressing File '%.*s'.",
  701.                         theFSS->name[0], &theFSS->name[1]);
  702.             AEdecompress(theFSS);
  703.             }
  704.         else if (fileInfo.fdType == 'MacB')
  705.             {
  706.             Feedback("AppleEvent: UnMacBinary File '%.*s'.",
  707.                         theFSS->name[0], &theFSS->name[1]);
  708.             AEUnMacBinary(theFSS);
  709.             }
  710.         else if (fileInfo.fdType == 'SITD' || fileInfo.fdType == 'SIT!')
  711.             {
  712.             Feedback("AppleEvent: UnStuffing File '%.*s'.",
  713.                         theFSS->name[0], &theFSS->name[1]);
  714.             AEUnStuffIt(theFSS);
  715.             }
  716.         else
  717.             {
  718.             if (     theFSS->name[theFSS->name[0]-3]            == '.'
  719.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 'h'
  720.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'q'
  721.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'x')
  722.                 {
  723.                 AEdecode_hqx(theFSS);
  724.                 }
  725.             else if (theFSS->name[theFSS->name[0]-1]            == '.'
  726.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'z')
  727.                 {
  728.                 AEdecompress(theFSS);
  729.                 }
  730.             else if (theFSS->name[theFSS->name[0]-2]            == '.'
  731.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'u'
  732.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'u')
  733.                 {
  734.                 AEuudecode(theFSS);
  735.                 }
  736.             else if (theFSS->name[theFSS->name[0]-3]            == '.'
  737.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 't'
  738.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'a'
  739.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'r')
  740.                 {
  741.                 AEExtract(theFSS);
  742.                 }
  743.             else if (theFSS->name[theFSS->name[0]-3]            == '.'
  744.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 's'
  745.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'i'
  746.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 't')
  747.                 {
  748.                 AEUnStuffIt(theFSS);
  749.                 }
  750.             else if (theFSS->name[theFSS->name[0]-2]            == '.'
  751.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'm'
  752.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'b')
  753.                 {
  754.                 AEUnMacBinary(theFSS);
  755.                 }
  756.             else if (theFSS->name[theFSS->name[0]-3]            == '.'
  757.                 &&    (theFSS->name[theFSS->name[0]-2]    | 0x20) == 't'
  758.                 &&    (theFSS->name[theFSS->name[0]-1]    | 0x20) == 'c'
  759.                 &&    (theFSS->name[theFSS->name[0]]        | 0x20) == 'l')
  760.                 {
  761.                 Feedback("AppleEvent: %s script '%.*s'.",
  762.                             (CheckOption() ? "Opening" : "Running"),
  763.                             theFSS->name[0], &theFSS->name[1]);
  764.                 myerr = OpenWD(theFSS->vRefNum, theFSS->parID, 'ERIK', &wdrefnum);
  765.                 if (myerr == noErr)
  766.                     SetVol(NULL, wdrefnum);
  767.                 else
  768.                     Feedback("Error %d OpenWD().", myerr);
  769.                 
  770.                 if (! CheckOption())
  771.                     run_named_tcl_script(theFSS->name, NULL, tcl_feedback_output);
  772. #ifdef TCLAPPL
  773.                 else
  774.                     do_tge_file_open(theFSS, 0);
  775. #endif
  776.                 
  777.                 if (myerr == noErr)
  778.                     myerr = CloseWD(wdrefnum);
  779.                 }
  780.             else
  781.                 Feedback("AppleEvent: What kind of document is '%.*s'?  Type '%4.4s'.",
  782.                             theFSS->name[0], &theFSS->name[1], &fileInfo.fdType);
  783.             }
  784.         }
  785.     
  786.     return result;
  787.     }
  788.