home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Graphics / GifScan 1.6 / Sources / Lib Sources / DSUtils.c < prev   
Encoding:
C/C++ Source or Header  |  1995-10-09  |  11.1 KB  |  396 lines  |  [TEXT/MMCC]

  1. /******************************************************************************
  2. **
  3. **  Project Name:    DropShell
  4. **     File Name:    DSUtils.c
  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. **    SCS            Stephan Somogyi
  15. **    LDR            Leonard Rosenthol
  16. **
  17. *******************************************************************************
  18. **                      R E V I S I O N   H I S T O R Y
  19. *******************************************************************************
  20. **
  21. **      Date        Author    Description
  22. **    ---------    ------    ---------------------------------------------
  23. **    23 Jun 94    LDR        Added a bunch of new routines for Marshall
  24. **    20 Feb 94    LDR        Added some new useful File System routines
  25. **    11 Dec 93    SCS        Universal Headers/UPPs (Phoenix 68k/PPC & PPCC)
  26. **                        Skipped System 6 compatible rev of DropShell source
  27. **                        Changed GetAppName to GetMyAppName (StdCLib conflict)
  28. **    12/09/91    LDR        Added the Apple event routines
  29. **    11/24/91    LDR        Original Version
  30. **
  31. ******************************************************************************/
  32.  
  33. #include <Dialogs.h>
  34. #include <Types.h>
  35.  
  36. #include "DSGlobals.h"
  37. #include "DSUtils.h"
  38. #include "DSAppleEvents.h"
  39.  
  40. /*
  41.     This routine is used to properly center an Alert before showing.
  42.     
  43.     It is per Human Interface specs by putting it in the top 1/3 of screen.
  44.     NOTE: This same technique can be used with DLOG resources as well.
  45. */
  46.  
  47. void CenterAlert ( short theID ) {
  48.     short        theX, theY;
  49.     AlertTHndl    theAlertHandle;
  50.     Rect        screen, alrt;
  51.     
  52.     theAlertHandle = (AlertTHndl) GetResource ( 'ALRT', theID );
  53.     if ( theAlertHandle != nil ) {
  54.         HLock ((Handle) theAlertHandle );
  55.  
  56.         alrt = (*theAlertHandle)->boundsRect;
  57.         screen = qd.screenBits.bounds;
  58.         
  59.         theX = (( screen.right - screen.left ) - (alrt.right - alrt.left )) >> 1;
  60.         theY = (( screen.bottom - screen.top ) + GetMBarHeight () - (alrt.bottom - alrt.top)) >> 1;
  61.         theY -= ( screen.bottom - screen.top ) >> 2;    // this moves it up for better viewing! 
  62.         OffsetRect ( &(*theAlertHandle)->boundsRect, theX - alrt.left, theY - alrt.top );
  63.     }
  64.         
  65.     SetCursor ( &qd.arrow );    // change this for code resources!
  66. }
  67.  
  68. /*
  69.     This routine is just a quick & dirty error reporter
  70. */
  71.  
  72. void ErrorAlert ( short stringListID, short stringIndexID, short errorID, Boolean fatal ) 
  73. {
  74.     #define    kAlertID    200
  75.     Str255    param, errorStr;
  76.  
  77.     NumToString ( errorID, errorStr );
  78.     GetIndString ( param, stringListID, stringIndexID );
  79.     ParamText ( param,  errorStr, nil, nil );
  80.     CenterAlert ( kAlertID );
  81.     (void) Alert ( kAlertID, nil );
  82.     if ( fatal ) ExitToShell();
  83. }
  84.  
  85. //** These routines use the Process Manager to give you information about yourself **
  86.  
  87.  
  88. void GetMyAppName(Str255 appName)    {
  89.     OSErr                err;
  90.     ProcessInfoRec        info;
  91.     ProcessSerialNumber    curPSN;
  92.  
  93.     err = GetCurrentProcess(&curPSN);
  94.     
  95.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  96.     info.processName = appName;                            // so it returned somewhere
  97.     info.processAppSpec = nil;                            // I don't care!
  98.  
  99.     err = GetProcessInformation(&curPSN, &info);
  100. }
  101.  
  102.  
  103. void GetAppFSSpec(FSSpec *appSpec)    {
  104.     OSErr                err;
  105.     Str255                appName;
  106.     ProcessInfoRec        info;
  107.     ProcessSerialNumber    curPSN;
  108.  
  109.     err = GetCurrentProcess(&curPSN);
  110.     
  111.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  112.     info.processName = appName;                            // so it returned somewhere
  113.     info.processAppSpec = appSpec;                        // so it can get returned!
  114.  
  115.     err = GetProcessInformation(&curPSN, &info);
  116. }
  117.  
  118. // ••• File Routines begin here ••• 
  119. /*
  120.     This routine is used to force the Finder (as much as is possible) to update
  121.     information about a newly changed file or folder.  
  122.     It does this by changing the modification date of the surrounding folder.
  123. */
  124. OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush)
  125. {
  126.     OSErr            lErr;
  127.     CInfoPBRec        lCBlk;
  128.     
  129.     if (pFSS->parID != 1)                            // if it's a vol then reuse the NameStr
  130.         lCBlk.dirInfo.ioNamePtr = 0L;
  131.     lCBlk.dirInfo.ioVRefNum = pFSS->vRefNum;        
  132.     lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  133.     lCBlk.dirInfo.ioFDirIndex = 0;
  134.     lCBlk.dirInfo.ioCompletion = 0;
  135.  
  136.     lErr = PBGetCatInfoSync(&lCBlk);
  137.     if (!lErr) {
  138.         GetDateTime(&lCBlk.dirInfo.ioDrMdDat);
  139.         lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  140.         lErr = PBSetCatInfoSync(&lCBlk);
  141.     
  142.         if ((!lErr) && (flush))
  143.             lErr = FlushVol(nil, pFSS->vRefNum);
  144.     }
  145.     
  146.     return (lErr);
  147. }
  148.  
  149. //    Is the file in use (busy)? 
  150. Boolean FSpIsBusy(FSSpecPtr theFile)
  151. {
  152.     Boolean        isBusy = false;
  153.     OSErr        err;
  154.     CInfoPBRec    cipb;
  155.     
  156.     cipb.hFileInfo.ioCompletion    = 0L;
  157.     cipb.hFileInfo.ioNamePtr    = theFile->name;
  158.     cipb.hFileInfo.ioVRefNum    = theFile->vRefNum;
  159.     cipb.hFileInfo.ioFDirIndex    = 0;
  160.     cipb.hFileInfo.ioDirID        = theFile->parID;
  161.     err = PBGetCatInfoSync(&cipb);
  162.     if (!err) {
  163.         isBusy = (cipb.hFileInfo.ioFlAttrib & 0x80) == 0x80;    // bit 7 = either fork open
  164.     }
  165.     return(isBusy);
  166. }
  167.  
  168. //    Is the “file” represented by this FSSpec really a folder? 
  169. Boolean    FSpIsFolder (FSSpecPtr theFSSpec) 
  170. {
  171.     OSErr    err;
  172.     CInfoPBRec    pb;
  173.     Str255    fName;
  174.     
  175.     if (theFSSpec->parID == fsRtParID)    // it's a volume!!
  176.         return(true);
  177.         
  178.     BlockMoveData (theFSSpec->name, fName, 32);
  179.     pb.hFileInfo.ioDirID        = theFSSpec->parID;
  180.     pb.hFileInfo.ioCompletion    = nil;
  181.     pb.hFileInfo.ioNamePtr        = fName;
  182.     pb.hFileInfo.ioVRefNum        = theFSSpec->vRefNum;
  183.     pb.hFileInfo.ioFDirIndex    = 0;
  184.     pb.hFileInfo.ioFVersNum        = 0;
  185.     err = PBGetCatInfoSync(&pb);
  186.     
  187.     if (!err) 
  188.     {
  189.         if (pb.hFileInfo.ioFlAttrib & ioDirMask)
  190.             return(true);
  191.     }
  192.     return(false);
  193. }
  194.  
  195. // Creates an empty handle to which FSSpecs could be added later!
  196. FSSpecArrayHandle    NewFSSpecList(void)
  197. {
  198.     return((FSSpecArrayHandle)NewHandle(0));
  199. }
  200.  
  201. // Releases memory used by an FSSpecList when all done
  202. void DisposeFSSpecList(FSSpecArrayHandle fsList)
  203. {
  204.     DisposeHandle((Handle)fsList);
  205. }
  206.  
  207. // Adds the new FSSpec to the end of an FSSpecList
  208. void AddToFSSpecList(FSSpec *fSpec, FSSpecArrayHandle fileList)
  209. {
  210.     Size    curSize, newSize;
  211.     long    numFiles;
  212.  
  213.     if ((!fileList) || (!fSpec)) return;    // if either is bogus, get out fast
  214.     
  215.     curSize = GetHandleSize((Handle)fileList);
  216.     numFiles = curSize / sizeof(FSSpec);
  217.     newSize = curSize + sizeof(FSSpec);
  218.     SetHandleSize((Handle)fileList, newSize);
  219.     if (MemError())    return;        // any problems, get out
  220.     
  221.     BlockMove(fSpec, &(*fileList)[numFiles], sizeof(FSSpec));
  222. }
  223.  
  224.  
  225. // ••• Apple event routines begin here ••• 
  226.  
  227. /*
  228.     This routine will create a targetDesc for sending to self.
  229.  
  230.     We take IM VI's advice and use the typePSN form with 
  231.     kCurrentProcess as the targetPSN.
  232. */
  233. OSErr GetTargetFromSelf (AEAddressDesc *targetDesc)
  234. {
  235.     ProcessSerialNumber    psn;
  236.  
  237.     psn.highLongOfPSN     = 0;
  238.     psn.lowLongOfPSN     = kCurrentProcess;
  239.  
  240.     return( AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber), targetDesc) );
  241. }
  242.  
  243. // This routine will create a targetDesc using the apps signature 
  244. OSErr GetTargetFromSignature (OSType processSig, AEAddressDesc *targetDesc)
  245. {
  246.     return( AECreateDesc(typeApplSignature, (Ptr)&processSig, sizeof(processSig), targetDesc) );
  247. }
  248.  
  249. // This routine will create a targetDesc by bringing up the PPCBrowser 
  250. OSErr GetTargetFromBrowser(Str255 promptStr, AEAddressDesc *targetDesc)
  251. {
  252.     OSErr        err;
  253.     TargetID    theTarget;
  254.     PortInfoRec    portInfo;
  255.     
  256.     err = PPCBrowser(promptStr, "\p", false, &theTarget.location, &portInfo, nil, "\p");
  257.     if (err == noErr) {
  258.         theTarget.name = portInfo.name;
  259.         err = AECreateDesc(typeTargetID, (Ptr)&theTarget, sizeof(TargetID), targetDesc);
  260.     }
  261.     return( err );
  262. }
  263.  
  264.  
  265. /*
  266.     This routine is the low level routine used by the SendODOCToSelf
  267.     routine.  It gets passed the list of files (in an AEDescList)
  268.     to be sent as the data for the 'odoc', builds up the event
  269.     and sends off the event.  
  270.  
  271.     It is broken out from SendODOCToSelf so that a SendODOCListToSelf could
  272.     easily be written and it could then call this routine - but that is left
  273.     as an exercise to the reader.
  274.     
  275.     Read the comments in the code for the order and details
  276. */
  277. void _SendDocsToSelf (AEDescList *aliasList)
  278. {
  279.     OSErr            err;
  280.     AEAddressDesc    theTarget;
  281.     AppleEvent        openDocAE, replyAE;
  282.  
  283. /*
  284.     First we create the target for the event.   We call another
  285.     utility routine for creating the target.
  286. */
  287.     err = GetTargetFromSelf(&theTarget);
  288.     if (err == noErr) 
  289.     {
  290.         // Next we create the Apple event that will later get sent.
  291.         err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, 
  292.                 &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &openDocAE);
  293.  
  294.         if (err == noErr) 
  295.         {
  296.             // Now add the aliasDescList to the openDocAE 
  297.             err = AEPutParamDesc(&openDocAE, keyDirectObject, aliasList);
  298.  
  299.             if (err == noErr) 
  300.             {
  301.                 /*
  302.                     and finally send the event
  303.                     Since we are sending to ourselves, no need for reply.
  304.                 */
  305.                 FailErr( err = AESend(&openDocAE, &replyAE, kAENoReply + kAECanInteract, 
  306.                         kAENormalPriority, 3600, nil, nil) );
  307.  
  308.                 // NOTE: Since we are not requesting a reply, we do not need to
  309.                 // need to dispose of the replyAE.  It is there simply as a 
  310.                 // placeholder.
  311.             }
  312.  
  313.             // Dispose of the aliasList descriptor
  314.             // We do this instead of the caller since it needs to be done
  315.             // before disposing the AEVT
  316.         
  317.             FailErr( err = AEDisposeDesc(aliasList) );
  318.         }
  319.  
  320.         // and of course dispose of the openDoc AEVT itself
  321.         FailErr(err = AEDisposeDesc(&openDocAE) );
  322.     }
  323. }
  324.  
  325. /*
  326.     This is the routine called by SelectFile to send a single odoc to ourselves.
  327.     It calls the above low level routine to do the dirty work of sending the AEVT -
  328.     all we do here is build a AEDescList of the file to be opened.
  329. */
  330. void SendODOCToSelf (FSSpec *theFileSpec)
  331. {
  332.  
  333.     OSErr        err;
  334.     AEDescList    aliasList;
  335.     AEDesc        aliasDesc;
  336.     AliasHandle    aliasH;
  337.     
  338.     //Create the descList to hold the list of files
  339.     err = AECreateList(nil, 0, false, &aliasList);
  340.  
  341.     if (err == noErr) 
  342.     {
  343.         // First we setup the type of descriptor 
  344.         aliasDesc.descriptorType = typeAlias;
  345.  
  346.         // Now we add the file to descList by creating an alias and then
  347.         // adding it into the descList using AEPutDesc
  348.  
  349.         err = NewAlias(nil, theFileSpec, &aliasH);
  350.         aliasDesc.dataHandle = (Handle)aliasH;
  351.         err = AEPutDesc(&aliasList, 0, &aliasDesc);
  352.         DisposeHandle((Handle)aliasH);
  353.  
  354.         // Now call the real gut level routine to do the dirty work
  355.         _SendDocsToSelf(&aliasList);
  356.  
  357.         // _SendDocsToSelf will dispose of aliasList for me
  358.     }
  359. }
  360.  
  361.  
  362. void SendQuitToSelf (void)
  363. {
  364.     OSErr            err;
  365.     AEAddressDesc    theTarget;
  366.     AppleEvent        quitAE, replyAE;
  367.  
  368. /*
  369.     First we create the target for the event.   We call another
  370.     utility routine for creating the target.
  371. */
  372.     err = GetTargetFromSelf(&theTarget);
  373.     if (err == noErr) {
  374.         // Next we create the Apple event that will later get sent. 
  375.         err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &quitAE);
  376.  
  377.         if (err == noErr) {
  378.             /*
  379.                 and finally send the event
  380.                 Since we are sending to ourselves, no need for reply.
  381.             */
  382.             err = AESend(&quitAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, nil, nil);
  383.  
  384.             /*
  385.                 NOTE: Since we are not requesting a reply, we do not need to
  386.                 need to dispose of the replyAE.  It is there simply as a 
  387.                 placeholder.
  388.             */
  389.         }
  390.  
  391.         // and of course dispose of the quit AEVT itself 
  392.         FailErr(err = AEDisposeDesc(&quitAE));
  393.     }
  394. }
  395.  
  396.