home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / what's new / sample code / human interface toolbox / packagetool / utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-22  |  10.9 KB  |  341 lines

  1. /*
  2.     file Utilities.c
  3.     
  4.     Description:
  5.     This file contains the a number of utility routines used in the
  6.     PackagTool example.  they have been moved to this file
  7.     to simplify the example.
  8.     
  9.     PackageTool is an application illustrating how to create application
  10.     packages in Mac OS 9.  It provides a simple interface for converting
  11.     correctly formatted folders into packages and vice versa.
  12.  
  13.     by John Montbriand, 1999.
  14.  
  15.     Copyright: © 1999 by Apple Computer, Inc.
  16.     all rights reserved.
  17.     
  18.     Disclaimer:
  19.     You may incorporate this sample code into your applications without
  20.     restriction, though the sample code has been provided "AS IS" and the
  21.     responsibility for its operation is 100% yours.  However, what you are
  22.     not permitted to do is to redistribute the source as "DSC Sample Code"
  23.     after having made changes. If you're going to re-distribute the source,
  24.     we require that you make it clear in the source that the code was
  25.     descended from Apple Sample Code, but that you've made changes.
  26.     
  27.     Change History (most recent first):
  28.     10/19/99 created by John Montbriand
  29. */
  30.  
  31. #include "Utilities.h"
  32. #include <QuickDraw.h>
  33. #include <Gestalt.h>
  34. #include <Palettes.h>
  35. #include <Threads.h>
  36. #include <fp.h>
  37. #include <FinderRegistry.h>
  38. #include <Resources.h>
  39. #include <Processes.h>
  40. #include <string.h>
  41.  
  42.  
  43.  
  44. /* ValidFSSpec verifies that *spec refers is formatted correctly, and it
  45.     verifies that it refers to an existing file in an existing directory on
  46.     and existing volume. If *spec is valid, the function returns noErr,
  47.     otherwise an error is returned. */
  48. OSErr ValidFSSpec(FSSpec *spec) {
  49.     FInfo fndrInfo;
  50.         /* check the name's size */
  51.     if (spec->name[0] + (sizeof(FSSpec) - sizeof(spec->name)) > sizeof(FSSpec)) return paramErr;
  52.         /* ckeck if it refers to a file */
  53.     return FSpGetFInfo(spec, &fndrInfo);
  54. }
  55.  
  56.  
  57. /* ResolveAliasQuietly resolves an alias using a fast search with no user interaction.  Our main loop
  58.     periodically resolves gFileAlias comparing the result to gTargetFile to keep the display up to date.
  59.     As a result, we would like the resolve alias call to be as quick as possible AND since the application
  60.     may be in the background when  it is called, we don't want any user interaction. */
  61. OSErr ResolveAliasQuietly(ConstFSSpecPtr fromFile, AliasHandle alias, FSSpec *target, Boolean *wasChanged) {
  62.     short aliasCount;
  63.     Boolean needsUpdate;
  64.     OSErr err;
  65.         /* set up locals */
  66.     aliasCount = 1;
  67.     needsUpdate = false;
  68.     *wasChanged = false;
  69.         /* call MatchAlias to resolve the alias.  
  70.             kARMNoUI = no user interaction,
  71.             kARMSearch = do a fast search. */
  72.     err = MatchAlias(NULL, (kARMNoUI | kARMSearch), alias, &aliasCount, target, &needsUpdate, NULL, NULL);
  73.     if (err == noErr) {
  74.             /* if the alias was changed, update it. */
  75.         err = UpdateAlias(fromFile, target, alias, wasChanged);
  76.     }
  77.     return err;
  78. }
  79.  
  80.  
  81.  
  82.  
  83. /* GrayOutBox grays out an area of the screen in the current grafport.  
  84.     *theBox is in local coordinates in the current grafport. This routine
  85.     is for direct screen drawing only.  */
  86. void GrayOutBox(Rect *theBox) {
  87.     long response;
  88.     Rect globalBox;
  89.     GDHandle maxDevice;
  90.     RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF}, rgbBlack = {0, 0, 0}, sForground, sBackground;
  91.     PenState penSave;
  92.         /* save the current drawing state */
  93.     GetPenState(&penSave);
  94.         /* if no color quickdraw, fail...*/
  95.     if (Gestalt(gestaltQuickdrawVersion, &response) != noErr) response = 0;
  96.     if (response >= gestalt8BitQD) {
  97.             /* get the device for the rectangle */
  98.         globalBox = *theBox;
  99.         LocalToGlobal((Point*) &globalBox.top);
  100.         LocalToGlobal((Point*) &globalBox.bottom);
  101.         maxDevice = GetMaxDevice(&globalBox);
  102.         if (maxDevice != NULL) {
  103.                 /* calculate the best gray */
  104.             if ( GetGray(maxDevice, &rgbWhite, &rgbBlack)) {
  105.                     /* draw over the area in gray using addMax transfer mode */
  106.                 GetForeColor(&sForground);
  107.                 GetBackColor(&sBackground);
  108.                 RGBForeColor(&rgbBlack);
  109.                 RGBBackColor(&rgbWhite);
  110.                 PenMode(addMax);
  111.                 PaintRect(theBox);
  112.                 RGBForeColor(&sForground);
  113.                 RGBBackColor(&sBackground);
  114.                     /* restore the pen state and leave */
  115.                 SetPenState(&penSave);
  116.                 return;
  117.             }
  118.         }
  119.     }
  120.         /* fall through to using the gray pattern */
  121.     PenPat(&qd.gray);
  122.     PenMode(notPatBic);
  123.     PaintRect(theBox);
  124.     SetPenState(&penSave);
  125. }
  126.  
  127.  
  128. /* ShowDragHiliteBox is called to hilite the drop box area in the
  129.     main window.  Here, we draw a 3 pixel wide border around *boxBounds.  */
  130. OSErr ShowDragHiliteBox(DragReference theDragRef, Rect *boxBounds) {
  131.     RgnHandle boxRegion, insetRegion;
  132.     OSErr err;
  133.     Rect box;
  134.         /* set up locals */
  135.     boxRegion = insetRegion = NULL;
  136.         /* create the region */
  137.     if ((boxRegion = NewRgn()) == NULL) { err = memFullErr; goto bail; }
  138.     if ((insetRegion = NewRgn()) == NULL) { err = memFullErr; goto bail; }
  139.     box = *boxBounds;
  140.     InsetRect(&box, -5, -5);
  141.     RectRgn(boxRegion, &box);
  142.     InsetRect(&box, 3, 3);
  143.     RectRgn(insetRegion, &box);
  144.     DiffRgn(boxRegion, insetRegion, boxRegion);
  145.         /* hilite the region */
  146.     err = ShowDragHilite(theDragRef, boxRegion, true);
  147. bail:
  148.         /* clean up and leave */
  149.     if (boxRegion != NULL) DisposeRgn(boxRegion);
  150.     if (insetRegion != NULL) DisposeRgn(insetRegion);
  151.     return err;
  152. }
  153.  
  154.  
  155.  
  156. /* UpdateRelativeAliasFile updates the alias file located at
  157.      aliasDest referring to the targetFile.  relative path
  158.      information is stored in the new file. */
  159. OSErr UpdateRelativeAliasFile(FSSpec *theAliasFile, FSSpec *targetFile) {
  160.     FInfo fndrInfo;
  161.     AliasHandle theAlias;
  162.     Boolean wasChanged;
  163.     short rsrc;
  164.     OSErr err;
  165.          /* set up locals */
  166.     rsrc = -1;
  167.          /* set up our the alias' file information */
  168.     err = FSpGetFInfo(targetFile, &fndrInfo);
  169.     if (err != noErr) goto bail;
  170.     if (fndrInfo.fdType == 'APPL')
  171.     fndrInfo.fdType = kApplicationAliasType;
  172.     fndrInfo.fdFlags = kIsAlias;
  173.          /* set the file information or the new file */
  174.     err = FSpSetFInfo(theAliasFile, &fndrInfo);
  175.     if (err != noErr) goto bail;
  176.          /* save the resource */
  177.     rsrc = FSpOpenResFile(theAliasFile, fsRdWrPerm);
  178.     if (rsrc == -1) { err = ResError(); goto bail; }
  179.     UseResFile(rsrc);
  180.     theAlias = (AliasHandle) Get1IndResource(rAliasType, 1);
  181.     if (theAlias == NULL) { err = resNotFound; goto bail; }
  182.     err = UpdateAlias(theAliasFile, targetFile, theAlias, &wasChanged);
  183.     if (err != noErr) goto bail;
  184.     if (wasChanged)
  185.         ChangedResource((Handle) theAlias);
  186.     CloseResFile(rsrc);
  187.     rsrc = -1;
  188.         /* done */
  189.     return noErr;
  190.  bail:
  191.     if (rsrc != -1) CloseResFile(rsrc);
  192.     return err;
  193.  }
  194.  
  195.  
  196. enum {
  197.     kFileSharingSignature = 'hhgg' /* Macintosh File Sharing */
  198. };
  199.  
  200. /* FileSharingAppIsRunning returns true if the file sharing
  201.     extension is running. */
  202. Boolean FileSharingAppIsRunning(void) {
  203.     ProcessSerialNumber psn;
  204.     ProcessInfoRec pinfo;
  205.  
  206.     psn.highLongOfPSN = psn.lowLongOfPSN = kNoProcess;
  207.     pinfo.processInfoLength = sizeof(ProcessInfoRec);
  208.     pinfo.processName = NULL;
  209.     pinfo.processAppSpec = NULL;
  210.     while (GetNextProcess(&psn) == noErr)
  211.         if (GetProcessInformation(&psn, &pinfo) == noErr)
  212.             if (pinfo.processSignature == kFileSharingSignature)
  213.                 return true;
  214.     return false;
  215. }
  216.  
  217.  
  218. /* FSSpecIsInDirectory returns true if the file system object
  219.     referred to by theSpec is somewhere in the directory referred
  220.     to by (vRefNum, dirID) */
  221. Boolean FSSpecIsInDirectory(FSSpec *theSpec, short vRefNum, long dirID) {
  222.     CInfoPBRec cat;
  223.     HParamBlockRec fvol, dirvol;
  224.     long currentDir;
  225.         /* check the volumes */
  226.     fvol.volumeParam.ioVRefNum = theSpec->vRefNum;
  227.     fvol.volumeParam.ioNamePtr = NULL;
  228.     fvol.volumeParam.ioVolIndex = 0;
  229.     if (PBHGetVInfoSync(&fvol)) return false;
  230.     dirvol.volumeParam.ioVRefNum = vRefNum;
  231.     dirvol.volumeParam.ioNamePtr = NULL;
  232.     dirvol.volumeParam.ioVolIndex = 0;
  233.     if (PBHGetVInfoSync(&dirvol) != noErr) return false;
  234.     if (fvol.volumeParam.ioVRefNum != dirvol.volumeParam.ioVRefNum) return false;
  235.         /* check if the directory is one of the file's parents */
  236.     currentDir = theSpec->parID;
  237.     while (true) {
  238.         if (dirID == currentDir) return true;
  239.         if (currentDir == 2) return false;
  240.             /* make sure it refers to a file in the package's directory */
  241.         memset(&cat, 0, sizeof(cat));
  242.         cat.dirInfo.ioNamePtr = NULL;
  243.         cat.dirInfo.ioVRefNum = theSpec->vRefNum;
  244.         cat.dirInfo.ioFDirIndex = -1;
  245.         cat.dirInfo.ioDrDirID = currentDir;
  246.         if (PBGetCatInfoSync(&cat) != noErr) return false;
  247.         currentDir = cat.dirInfo.ioDrParID;
  248.     }
  249. }
  250.  
  251.  
  252. /* FSSpecIsAFolder returns true if the FSSpec pointed
  253.     to by target refers to a folder. */
  254. Boolean FSSpecIsAFolder(FSSpec *target) {
  255.     CInfoPBRec cat;
  256.     OSErr err;
  257.         /* check the target's flags */
  258.     cat.dirInfo.ioNamePtr = target->name;
  259.     cat.dirInfo.ioVRefNum = target->vRefNum;
  260.     cat.dirInfo.ioFDirIndex = 0;
  261.     cat.dirInfo.ioDrDirID = target->parID;
  262.     err = PBGetCatInfoSync(&cat);
  263.     if (err != noErr) return false;
  264.     return ((cat.dirInfo.ioFlAttrib & 16) != 0);
  265. }
  266.  
  267.  
  268. /* ShowChangesInFinderWindow asks the finder redraw a directory
  269.     window by either sending a update container event to the
  270.     finder if this facility exists, or by bumping the parent directorie's
  271.     modification date */
  272. OSErr ShowChangesInFinderWindow(short vRefNum, long dirID) {
  273.     OSErr err;
  274.     long response;
  275.     CInfoPBRec cat;
  276.     Str255 name;
  277.         /* get information about the directory */
  278.     cat.hFileInfo.ioNamePtr = name;
  279.     cat.hFileInfo.ioVRefNum = vRefNum;
  280.     cat.hFileInfo.ioDirID = dirID;
  281.     cat.hFileInfo.ioFDirIndex = -1;
  282.     if ((err = PBGetCatInfoSync(&cat)) != noErr) return err;
  283.         /* determine what we can do... */
  284.     if (Gestalt(gestaltFinderAttr, &response) != noErr) response = 0;
  285.     if ((response & (1<<gestaltOSLCompliantFinder)) != 0) {
  286.         AppleEvent the_apple_event, the_reply;
  287.         AEAddressDesc target_desc;
  288.         FSSpec spec;
  289.         OSType app_creator;
  290.         long actualSize, the_error;
  291.         DescType actualType;
  292.     
  293.             /* set up a recoverable state */
  294.         AECreateDesc(typeNull, NULL, 0, &the_apple_event);
  295.         AECreateDesc(typeNull, NULL, 0, &target_desc);
  296.         AECreateDesc(typeNull, NULL, 0, &the_reply);
  297.  
  298.             /* create an update event targeted at the finder */
  299.         app_creator = 'MACS';
  300.         err = AECreateDesc(typeApplSignature, (Ptr) &app_creator,
  301.             sizeof(app_creator), &target_desc);
  302.         if (err != noErr) goto send_update_abort;
  303.         err = AECreateAppleEvent(kAEFinderSuite, kAEUpdate,
  304.             &target_desc, kAutoGenerateReturnID,
  305.             kAnyTransactionID, &the_apple_event);
  306.         if (err != noErr) goto send_update_abort;
  307.  
  308.             /* add the FSSpec parameter */
  309.         err = FSMakeFSSpec(vRefNum, cat.dirInfo.ioDrParID, name, &spec);
  310.         if (err != noErr) goto send_update_abort;
  311.         err = AEPutParamPtr(&the_apple_event, keyDirectObject, typeFSS, &spec, sizeof(FSSpec));
  312.         if (err != noErr) goto send_update_abort;
  313.  
  314.             /* send the apple event */
  315.         err = AESend(&the_apple_event, &the_reply, kAENoReply,
  316.             kAENormalPriority, kNoTimeOut, NULL, NULL);
  317.         
  318.         err = AEGetParamPtr(&the_reply, keyErrorNumber, typeLongInteger,
  319.             &actualType, &the_error, 4, &actualSize);
  320.         if (err == errAEDescNotFound)
  321.             err = noErr;
  322.         else if (err == noErr)
  323.             err = the_error;
  324.  
  325.     send_update_abort:
  326.         AEDisposeDesc(&the_apple_event);
  327.         AEDisposeDesc(&target_desc);
  328.         AEDisposeDesc(&the_reply);
  329.  
  330.     } else {    /* bump the date for the directory so the finder notices */
  331.         unsigned long secs;
  332.         GetDateTime(&secs);
  333.         cat.hFileInfo.ioFlMdDat = (secs == cat.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
  334.         cat.hFileInfo.ioDirID = cat.dirInfo.ioDrParID;
  335.         err = PBSetCatInfoSync(&cat);
  336.     }
  337.     return err;
  338. }
  339.  
  340.  
  341.