home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Frameworks / DropShell Pascal / DSUtils.p < prev    next >
Encoding:
Text File  |  1994-05-27  |  9.6 KB  |  343 lines  |  [TEXT/MPS ]

  1. {******************************************************************************
  2. **
  3. **  Project Name:    DropShell
  4. **     File Name:    DSUtils.p
  5. **
  6. **   Description:    Utility routines that may be useful to DropBoxes
  7. **
  8. *******************************************************************************
  9. **                       A U T H O R   I D E N T I T Y
  10. *******************************************************************************
  11. **
  12. **    Initials    Name
  13. **    --------    -----------------------------------------------
  14. **    LDR            Leonard Rosenthol
  15. **
  16. *******************************************************************************
  17. **                      R E V I S I O N   H I S T O R Y
  18. *******************************************************************************
  19. **
  20. **      Date        Time    Author    Description
  21. **    --------    -----    ------    ---------------------------------------------
  22. **    12/09/91            LDR        Added the Apple event routines
  23. **    11/24/91            LDR        Original Version
  24. **
  25. ******************************************************************************}
  26. UNIT DSUtils;
  27. INTERFACE
  28.  
  29. {$IFC THINK_Pascal}
  30.     USES
  31.         Aliases, AppleEvents, PPCToolbox, Processes, Script, DSGlobals;    {just the DropShell files}
  32. {$ELSEC}
  33.     USES
  34.     { First load standard interface files}
  35.         MemTypes, QuickDraw, 
  36.  
  37.     { Now include the stuff from OSIntf }
  38.         OSIntf, 
  39.  
  40.     { Now Include the stuff from ToolIntf.p }
  41.         ToolIntf, Packages, GestaltEqu, 
  42.  
  43.     { Then any OTHER Toolbox interfaces... }
  44.         Files, Aliases, AppleEvents, PPCToolbox, Processes, 
  45.  
  46.     { And finally any files from DropShell }
  47.         DSGlobals;
  48. {$ENDC THINK_Pascal}
  49.  
  50. {---------------------}
  51. {Interface Definitions}
  52. {---------------------}
  53.  
  54.     PROCEDURE CenterAlert (theID: integer);
  55.     PROCEDURE ErrorAlert (stringListID, stringIndexID, errorID: integer);
  56.  
  57.     PROCEDURE GetAppName (VAR appName: Str255);
  58.     PROCEDURE GetAppFSSpec (VAR appSpec: FSSpec);
  59.  
  60.     FUNCTION GetTargetFromSelf (VAR targetDesc: AEAddressDesc): OSErr;
  61.     FUNCTION GetTargetFromSignature (processSig: OSType; VAR targetDesc: AEAddressDesc): OSErr;
  62.     FUNCTION GetTargetFromBrowser (promptStr: Str255; VAR targetDesc: AEAddressDesc): OSErr;
  63.  
  64.     PROCEDURE SendODOCToSelf (theFileSpec: FSSpec);
  65.     PROCEDURE SendQuitToSelf;
  66.  
  67. IMPLEMENTATION
  68. {$S Main}
  69.  
  70.     {
  71.         This routine is used to properly center an Alert before showing.
  72.         
  73.         It is per Human Interface specs by putting it in the top 1/3 of screen.
  74.         NOTE: This same technique can be used with DLOG resources as well.
  75.     }    
  76.     PROCEDURE CenterAlert (theID: integer);
  77.         VAR
  78.             theX, theY: INTEGER;
  79.             theAlertHandle: AlertTHndl;
  80.     BEGIN
  81.         theAlertHandle := AlertTHndl(GetResource('ALRT', theID));
  82.         IF theAlertHandle <> NIL THEN
  83.         BEGIN
  84.             HLock(Handle(theAlertHandle));
  85.             WITH theAlertHandle^^ DO
  86.             BEGIN
  87.                 WITH qd.screenBits DO
  88.                 BEGIN
  89.                     theX := ((bounds.right - bounds.left) - (boundsRect.right - boundsRect.left)) DIV 2;
  90.                     theY := ((bounds.bottom - bounds.top) + GetMBarHeight - (boundsRect.bottom - boundsRect.top)) DIV 2;
  91.                     theY := theY - ((bounds.bottom - bounds.top) DIV 4);    {this moves it up for better viewing!}
  92.                 END;
  93.                 OffsetRect(boundsRect, theX - boundsRect.left, theY - boundsRect.top);
  94.             END;
  95.         END;
  96.         SetCursor(qd.arrow);    {if you use this routine in a code resource, change this!}
  97.     END;
  98.  
  99.     {
  100.         This routine is just a quick & dirty error reporter
  101.     }
  102.     PROCEDURE ErrorAlert (stringListID, stringIndexID, errorID: integer);
  103.         CONST
  104.             alertID = 200;
  105.         VAR
  106.             item: integer;
  107.             param, errorStr: Str255;
  108.     BEGIN
  109.         NumToString(errorID, errorStr);
  110.         GetIndString(param, stringListID, stringIndexID);
  111.         ParamText(param, errorStr, '', '');
  112.         CenterAlert(alertID);
  113.         item := Alert(alertID, NIL);
  114.     END;
  115.  
  116. {*** These routines use the Process Manager to give you information about yourself ***}
  117.  
  118.     PROCEDURE GetAppName (VAR appName: Str255);
  119.         VAR
  120.             err: OSErr;
  121.             info: ProcessInfoRec;
  122.             curPSN: ProcessSerialNumber;
  123.     BEGIN
  124.         err := GetCurrentProcess(curPSN);
  125.  
  126.         WITH info DO
  127.         BEGIN
  128.             processInfoLength := sizeof(ProcessInfoRec);    {ALWAYS USE sizeof!}
  129.             processName := @appName;                        {so it returned somewhere}
  130.             processAppSpec := NIL;                            {I don't care!}
  131.         END;
  132.         err := GetProcessInformation(curPSN, info);
  133.     END;
  134.  
  135.     PROCEDURE GetAppFSSpec (VAR appSpec: FSSpec);
  136.         VAR
  137.             err: OSErr;
  138.             info: ProcessInfoRec;
  139.             appName: Str255;
  140.             curPSN: ProcessSerialNumber;
  141.     BEGIN
  142.         err := GetCurrentProcess(curPSN);
  143.  
  144.         WITH info DO
  145.         BEGIN
  146.             processInfoLength := sizeof(ProcessInfoRec);    {ALWAYS USE sizeof!}
  147.             processName := @appName;                        {so it returned somewhere}
  148.             processAppSpec := @appSpec;                        {and here's where the spec goes}
  149.         END;
  150.         err := GetProcessInformation(curPSN, info);
  151.     END;
  152.  
  153.  
  154. { ••• Apple event routines begin here ••• }
  155.  
  156. {
  157.     This routine will create a targetDesc for sending to self.
  158.  
  159.     We take IM VI's advice and use the typePSN form with 
  160.     kCurrentProcess as the targetPSN.
  161. }
  162.     FUNCTION GetTargetFromSelf (VAR targetDesc: AEAddressDesc): OSErr;
  163.         VAR
  164.             err: OSErr;
  165.             psn: ProcessSerialNumber;
  166.     BEGIN
  167.         WITH psn DO
  168.         BEGIN
  169.             highLongOfPSN := 0;
  170.             lowLongOfPSN := kCurrentProcess;
  171.         END;
  172.         err := AECreateDesc(typeProcessSerialNumber, @psn, sizeof(ProcessSerialNumber), targetDesc);
  173.         GetTargetFromSelf := err;
  174.     END;
  175.  
  176. {This routine will create a targetDesc using the apps signature}
  177.     FUNCTION GetTargetFromSignature (processSig: OSType; VAR targetDesc: AEAddressDesc): OSErr;
  178.         VAR
  179.             err: OSErr;
  180.  
  181.     BEGIN
  182.         err := AECreateDesc(typeApplSignature, @processSIG, sizeof(processSig), targetDesc);
  183.         GetTargetFromSignature := err;
  184.     END;
  185.  
  186. {This routine will create a targetDesc by bringing up the PPCBrowser}
  187.     FUNCTION GetTargetFromBrowser (promptStr: Str255; VAR targetDesc: AEAddressDesc): OSErr;
  188.         VAR
  189.             err: OSErr;
  190.             theTarget: TargetID;
  191.             portInfo: PortInfoRec;
  192.  
  193.     BEGIN
  194.         err := PPCBrowser(promptStr, '', FALSE, theTarget.location, portInfo, NIL, '');
  195.         IF (err = noErr) THEN
  196.         BEGIN
  197.             theTarget.name := portInfo.name;
  198.             err := AECreateDesc(typeTargetID, @theTarget, sizeof(TargetID), targetDesc);
  199.         END;
  200.         GetTargetFromBrowser := err;
  201.     END;
  202.  
  203.  
  204. {
  205.     This routine is the low level routine used by the SendODOCToSelf
  206.     routine.  It gets passed the list of files (in an AEDescList)
  207.     to be sent as the data for the 'odoc', builds up the event
  208.     and sends off the event.  
  209.  
  210.     It is broken out from SendODOCToSelf so that a SendODOCListToSelf could
  211.     easily be written and it could then call this routine - but that is left
  212.     as an exercise to the reader.
  213.     
  214.     Read the comments in the code for the order and details
  215. }
  216.     PROCEDURE _SendDocsToSelf (aliasList: AEDescList);
  217.         VAR
  218.             err: OSErr;
  219.             theTarget: AEAddressDesc;
  220.             openDocAE: AppleEvent;
  221.             replyAE: AppleEvent;
  222.  
  223.     BEGIN
  224.     {
  225.         First we create the target for the event.   We call another
  226.         utility routine for creating the target.
  227.     }
  228.         err := GetTargetFromSelf(theTarget);
  229.         IF (err = noErr) THEN
  230.         BEGIN
  231.         {Next we create the Apple event that will later get sent.}
  232.             err := AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, theTarget, kAutoGenerateReturnID, kAnyTransactionID, openDocAE);
  233.  
  234.             IF err = noErr THEN
  235.             BEGIN
  236.             {Now add the aliasDescList to the openDocAE}
  237.                 err := AEPutParamDesc(openDocAE, keyDirectObject, aliasList);
  238.  
  239.                 IF err = noErr THEN
  240.                 BEGIN
  241.                 {
  242.                     and finally send the event
  243.                     Since we are sending to ourselves, no need for reply.
  244.                 }
  245.                     err := AESend(openDocAE, replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NIL, NIL);
  246.  
  247.                 {
  248.                     NOTE: Since we are not requesting a reply, we do not need to
  249.                     need to dispose of the replyAE.  It is there simply as a 
  250.                     placeholder.
  251.                 }
  252.                 END;
  253.  
  254.             {    
  255.                 Dispose of the aliasList descriptor
  256.                 We do this instead of the caller since it needs to be done
  257.                 before disposing the AEVT
  258.             }
  259.                 err := AEDisposeDesc(aliasList);
  260.             END;
  261.  
  262.         {and of course dispose of the openDoc AEVT itself}
  263.             err := AEDisposeDesc(openDocAE);
  264.         END;
  265.     END;
  266.  
  267. {
  268.     This is the routine called by SelectFile to send a single odoc to ourselves.
  269.     
  270.     It calls the above low level routine to do the dirty work of sending the AEVT -
  271.     all we do here is build a AEDescList of the file to be opened.
  272. }
  273.     PROCEDURE SendODOCToSelf (theFileSpec: FSSpec);
  274.         VAR
  275.             err: OSErr;
  276.             aliasList: AEDescList;
  277.             aliasDesc: AEDesc;
  278.             aliasH: AliasHandle;
  279.     BEGIN
  280.     {Create the descList to hold the list of files}
  281.         err := AECreateList(NIL, 0, FALSE, aliasList);
  282.  
  283.         IF err = noErr THEN
  284.         BEGIN
  285.         {First we setup the type of descriptor}
  286.             aliasDesc.descriptorType := typeAlias;
  287.  
  288.         {
  289.             Now we add the file to descList by creating an alias and then
  290.             adding it into the descList using AEPutDesc
  291.         }
  292.             err := NewAlias(NIL, theFileSpec, aliasH);
  293.             aliasDesc.dataHandle := Handle(aliasH);
  294.             err := AEPutDesc(aliasList, 0, aliasDesc);
  295.             DisposHandle(Handle(aliasH));
  296.  
  297.         {Now call the real gut level routine to do the dirty work}
  298.             _SendDocsToSelf(aliasList);
  299.  
  300.         {_SendDocsToSelf will dispose of aliasList for me}
  301.         END;
  302.     END;
  303.  
  304.  
  305.     PROCEDURE SendQuitToSelf;
  306.         VAR
  307.             err: OSErr;
  308.             theTarget: AEAddressDesc;
  309.             QuitAE: AppleEvent;
  310.             replyAE: AppleEvent;
  311.  
  312.     BEGIN
  313.     {
  314.         First we create the target for the event.   We call another
  315.         utility routine for creating the target.
  316.     }
  317.         err := GetTargetFromSelf(theTarget);
  318.         IF (err = noErr) THEN
  319.         BEGIN
  320.         {Next we create the Apple event that will later get sent.}
  321.             err := AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, theTarget, kAutoGenerateReturnID, kAnyTransactionID, QuitAE);
  322.  
  323.             IF err = noErr THEN
  324.             BEGIN
  325.             {
  326.                 and send the event
  327.                 Since we are sending to ourselves, no need for reply.
  328.             }
  329.                 err := AESend(QuitAE, replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NIL, NIL);
  330.  
  331.             {
  332.                 NOTE: Since we are not requesting a reply, we do not need to
  333.                 need to dispose of the replyAE.  It is there simply as a 
  334.                 placeholder.
  335.             }
  336.             END;
  337.  
  338.         {Dispose of the quit AEVT itself}
  339.             err := AEDisposeDesc(QuitAE);
  340.         END;
  341.     END;
  342.  
  343. END.