From: joshr@kronos.arc.nasa.gov (Joshua Rabinowitz-Summer-91)
Subject: Re: Sending AEs to hypercard
Organization: NASA/ARC Information Sciences Division
Date: Sat, 22 Aug 1992 00:19:28 GMT

In article <EeYJUtS00iUx04XlJV@andrew.cmu.edu> "George J. Baxter" <gb2a+@andrew.cmu.edu> writes:
>Gurus:
>    I want to send a string to Hypercard.  I'm using hypercard as a
>front end and I want to send back an error message if I get one.  I
>don't want Hypercard to wait around in any XCMD while I'm looking for my
>error string since there might not be one, or it might be a long time
>coming.  So I want to use Hypercard's built in AE handlers.  I know that
>2.1 supports appleEvents, but how specifically do I address the AE
>handler in hypercard?  The little New Features Guide gives me some
>hints. For example, I could send the appleEvent under class 'misc',  and
>ID 'dosc' with my string being "put <my error string here>"
>or something.  The question I have is where do I put this error string? 
>The 'dosc' ID is described as "interpret the return-delimited list
>accompanying this Apple event as a script and execute it."  
>    Hypercard provides the command "request AppleEvent data", which I
>guess is where the strings in question reside, but again, in my code,
>how do I hand it to Hypercard?  
>    Thanks!
>        -George Baxter
>-----------------------
>gb2a@andrew.cmu.edu		    baxter@a.cfr.cmu.edu

At the risk of giving away some industry trade secrets,
or just throuwing away my work, I'll GIVE you guys this completely
working code.  It sends a string to hypercard
to be interpreted as a script.  I never got as far as getting hypercard
to return a message like OK or ERROR,though (or maybe
I check for it wrong -- I dont know).  If someone would like
to outline how this would be added to this code, I'd be greatful (but
fair's fair) -- here ya go, netters, the fruit of a bunch of labor.

THis code WORKS.

written under THINK C5.02
--------- HEADER __________

#include <AppleEvents.h>
#include <stdio.h>  // for printf()
#include <string.h>


#define kHypercardSignature 'WILD'
#define kHypercardMessageEventClass 'misc'
#define kHypercardMessageEventID	'dosc'


/* PROTOTYPES */
pascal OSErr myEventHandler(AppleEvent *event, AppleEvent *reply, long ref);
Boolean SendToHypercard(char *messageToSend);
pascal Boolean myIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle mouseRgn);
pascal Boolean HypercardFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
Boolean FindHypercardProcessNumber(ProcessSerialNumber *process);
Boolean FindAProcess(OSType signature, ProcessSerialNumber *process, 
			       ProcessInfoRec *infoRec, FSSpecPtr aFSSPec);   
/* from InsideMac VI, p. 29-11, "process manager" */

  ---------SOURCE---------

nclude "SendToHyp.h"
#include <Exceptions.h>
#include "Constants.h"
#include <TBUtilities.h>


Boolean SendToHypercard(char *messageToSend) 
{
  // from Programming for SYS7, p. 145
   // pseudocode:
   
   // determine target address using PPCBrowser() 
   // or GetNextProcess() and GetProcessInformation()
   
   // create address descriptor from above info
   
   // create apple event with AECreateAppleEvent() and pass it address descriptor
   //  use AEManager to add descriptors with AEPutParamPtr or AEPutParamDesc
   
   // call AESend
   // check for errors
   // dispose of copies of descriptor records
   // process the AEReply
   
   
   
   AEAddressDesc 	theAddressDesc;
   AEDesc		theResultDescriptor;
   AppleEvent 	theAE, theReply;
   OSErr 		myError, sendError;
   Str255 		myPrompt = "\pPlease Locate Hypercard:";
   Str255 		myListTitle = "\pHypercard Hosts:";
   TargetID 	myTarget;
   PortInfoRec	myPortInfo;
   DescType 	actualType, theDescriptorType;
   long 		eventError, actualSize, theResultSize;
   ProcessSerialNumber process;
   
   // printf("%s\n", messageToSend);
   /*****
   myError = PPCBrowser(myPrompt, myListTitle, FALSE, &(myTarget.location), 
      &myPortInfo, (PPCFilterProcPtr)HypercardFilter, 0L);
   FailOSErr(myError);
   
   BlockMove(&myPortInfo.name, &myTarget.name, sizeof(PPCPortRec) );
   
   
   myError = AECreateDesc( typeTargetID, (Ptr)(&myTarget), sizeof(TargetID),  
      &theAddressDesc);  
      // loads into address desciptor
   FailOSErr(myError);
   *****/
   
   if (FindHypercardProcessNumber(&process) == FALSE)
      return FALSE;
   
   myError = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, 
      sizeof(process), &theAddressDesc);
   FailOSErr(myError);

   myError = AECreateAppleEvent(kHypercardMessageEventClass, kHypercardMessageEventID, 
      &theAddressDesc, kAutoGenerateReturnID, kAnyTransactionID, &theAE); 
   FailOSErr(myError);
   
   myError = AEDisposeDesc( &theAddressDesc);   /* we don't need it anymore */
   FailOSErr(myError);
      
   myError = AEPutParamPtr(&theAE, keyDirectObject, typeChar, 
      messageToSend, strlen(messageToSend) );
   FailOSErr(myError);
   
   sendError = AESend(&theAE, &theReply, kAEQueueReply, kAENormalPriority, 
      kNoTimeOut, myIdleProc, 0L);
   
   if (sendError) {
      myError = AEDisposeDesc(&theAE);
      FailOSErr(sendError);
      return FALSE;
   }
      
   myError = AEDisposeDesc(&theAE);
   FailOSErr(myError);
   
   myError = AEGetParamPtr( &theReply, keyErrorNumber, typeLongInteger, &actualType,
      (Ptr)(&eventError), sizeof(eventError), &actualSize);
   if (myError != errAEDescNotFound) {
      if (myError) {
         myError = AEDisposeDesc( &theReply);
         // SysBeep(1);
         return FALSE;
      } else {
         if (eventError != noErr) {
            myError=AEDisposeDesc( &theReply);
            // SysBeep(1);
            return FALSE;
         }
      }
   }
   
   myError = AEGetParamDesc(&theReply, keyDirectObject, typeChar, 
      &theResultDescriptor);
   if (myError) { /* no direct object exists ! */
      myError = AEDisposeDesc( &theReply);
      // SysBeep(1);
      // FailOSErr(myError);
   }
   
   myError = AESizeOfParam( &theReply, keyDirectObject, &theDescriptorType,
      &theResultSize);
   // FailOSErr(myError);
   
   myError = ZeroScrap();
   // FailOSErr(myError);
   
   myError = PutScrap( theResultSize, 'TEXT', *theResultDescriptor.dataHandle);
   //FailOSErr(myError);
   
   myError = AEDisposeDesc(&theResultDescriptor);
   // FailOSErr(myError);
   
   myError = AEDisposeDesc(&theReply);
   
   return TRUE;
}

  
pascal Boolean myIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle mouseRgn)
{
   EventRecord testEvent;
   Boolean gotKbd;
   char key;
   
   gotKbd = GetOSEvent(keyDownMask, &testEvent);
   
   if (gotKbd) {
      key = testEvent.message & charCodeMask;
      if ( (key == '.') && (testEvent.modifiers & cmdKey) )
         return TRUE;
   }
   switch(theEvent->what) {
      case nullEvent:
      break;
   }
   return FALSE;
}
  

/*** FIND HYPERCARD PROCESS NUMBER ****/
Boolean FindHypercardProcessNumber(ProcessSerialNumber *process)
{
   OSType sig = kHypercardSignature;
   Boolean found = FALSE;
   ProcessInfoRec pir;
   FSSpec fssp;
   
   found =  FindAProcess(sig, process, &pir, &fssp);
   
   if (found == FALSE) {
      ParamText("\pcouldn't find hypercard running", NULL, NULL, NULL);
      PositionDialog('ALRT', ALRTgeneral);
	  InitCursor();
	  Alert(ALRTgeneral, NULL);
   }
   return found;
}  
   
/* from InsideMac VI, p. 29-11, "process manager" */

Boolean FindAProcess(OSType signature, ProcessSerialNumber *process, 
   ProcessInfoRec *infoRec, FSSpecPtr aFSSpecPtr)
{
   process->highLongOfPSN = 0;
   process->lowLongOfPSN = kNoProcess;  // start from the beginning
   
   infoRec->processInfoLength = sizeof(ProcessInfoRec);
   infoRec->processName = (StringPtr)(NewPtr(32));
   infoRec->processAppSpec = aFSSpecPtr;
   
   while (GetNextProcess(process) == noErr) {
      if (GetProcessInformation(process, infoRec) == noErr) {
         if (infoRec->processType == ((long)'APPL') &&
             infoRec->processSignature == signature) {
            return TRUE;
         }
      }
   }
   SysBeep(1);
   return FALSE;
}

-- 
----------------------------------
#include <std/disclaimer.h>     Josh Rabinowitz, Mac TCL programmer
joshr@kronos.arc.nasa.gov
"Send a salami to your boy in the army" - Katz's delicatessen, NYC