home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / flipsrc.sit / flab.c next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  6.6 KB  |  266 lines

  1. /* flab.c
  2.  * ⌐ 1992 - Michael S. Engber - All Rights Reserved
  3.  */
  4.  
  5. #include <AppleEvents.h>
  6. #include <Finder.h>
  7. #include "ierror.h"
  8. #include "flab.h"
  9.  
  10.  
  11. /* Looks through running processes for one with the specified type and signature.
  12.  * Passes back the its ProcessSerialNumber & FSSpec.
  13.  */
  14. static OSErr FindProcess(OSType processType, OSType processSig, ProcessSerialNumberPtr psn_p, FSSpecPtr spec_p){
  15.     ProcessInfoRec    pinfo;
  16.     pinfo.processName        = NULL;
  17.     pinfo.processInfoLength    = sizeof(pinfo);
  18.     pinfo.processAppSpec    = spec_p;
  19.     
  20.     psn_p->highLongOfPSN = 0;
  21.     psn_p->lowLongOfPSN  = kNoProcess;
  22.     
  23.     while(!GetNextProcess(psn_p)){
  24.         if(!GetProcessInformation(psn_p,&pinfo)    &&
  25.             pinfo.processType        == processType    &&
  26.             pinfo.processSignature    == processSig){
  27.                 return noErr;
  28.         }
  29.     }
  30.     return -1;
  31. }
  32.  
  33. /* Sends the specified process a quit AE.
  34.  */
  35. static OSErr QuitProcess(ProcessSerialNumberPtr psn_p, Boolean wait){
  36.     OSErr                err;
  37.     AppleEvent            ae;
  38.     AppleEvent            aeReply;
  39.     AEAddressDesc        aeAddr;
  40.     
  41.     if(err=AECreateDesc(typeProcessSerialNumber,(Ptr)psn_p,sizeof(ProcessSerialNumber),&aeAddr)) return err;
  42.     if(err=AECreateAppleEvent(kCoreEventClass,kAEQuitApplication,&aeAddr,0,kAnyTransactionID,&ae)){
  43.         AEDisposeDesc(&aeAddr);
  44.         return err;
  45.     }
  46.     err = AESend(&ae,&aeReply,wait?kAEWaitReply:kAENoReply,kAENormalPriority,kNoTimeOut,NULL,NULL);
  47.     AEDisposeDesc(&ae);
  48.     AEDisposeDesc(&aeAddr);
  49.     AEDisposeDesc(&aeReply);
  50.     return err;
  51. }
  52.  
  53.  
  54. /* Passes back the Finder's ProcessSerialNumber & FSSpec. */
  55. static OSErr FindFinder(ProcessSerialNumberPtr psn_p, FSSpecPtr spec_p){
  56.     return FindProcess('FNDR','MACS',psn_p,spec_p);
  57. }
  58.  
  59. /* Passes back the File Sharing Extension's ProcessSerialNumber. */
  60. static OSErr FindFileShareExt(ProcessSerialNumberPtr psn_p){
  61.     FSSpec    danQuayle;
  62.     return FindProcess('INIT','hhgg',psn_p,&danQuayle);
  63. }
  64.  
  65.  
  66. /* Sends the Finder a quit AE.
  67.  * Passes back the Finder's FSSpec for re-Launching it.
  68.  */
  69. static OSErr QuitFinder(FSSpecPtr finderSpec_p){
  70.     OSErr                err;
  71.     ProcessSerialNumber finderPsn;
  72.     ProcessSerialNumber fSharePsn;
  73.  
  74.     if(err=FindFinder(&finderPsn,finderSpec_p)) return err;
  75.  
  76.     /* find & quit the File Sharing Extension */
  77.     if(!FindFileShareExt(&fSharePsn)){
  78.         if(err=QuitProcess(&fSharePsn,false)) return err;
  79.     }
  80.  
  81.     /* now quit the Finder */
  82.     return QuitProcess(&finderPsn,true);
  83. }
  84.  
  85.  
  86. /* Launches the Finder */
  87. static OSErr LaunchFinder(FSSpecPtr finderSpec_p){
  88.     LaunchParamBlockRec    pb;
  89.     pb.launchBlockID        = extendedBlock;
  90.     pb.launchEPBLength        = extendedBlockLen;
  91.     pb.launchControlFlags    = launchContinue + launchNoFileFlags;
  92.     pb.launchAppSpec        = finderSpec_p;
  93.     pb.launchAppParameters    = NULL;
  94.     
  95.     return LaunchApplication(&pb);
  96. }
  97.  
  98.  
  99.  
  100.  
  101. static Boolean CanHackDTDB(short vRefNum){
  102.  
  103.         OSErr                    err;
  104.         HParamBlockRec            pb;
  105.         GetVolParmsInfoBuffer    vParms;
  106.  
  107.         pb.ioParam.ioNamePtr    = NULL;
  108.         pb.ioParam.ioVRefNum    = vRefNum;
  109.         pb.ioParam.ioBuffer        = (Ptr)&vParms;
  110.         pb.ioParam.ioReqCount    = sizeof(vParms);
  111.         return    PBHGetVolParmsSync(&pb) == noErr &&
  112.                  ((1L<<bHasDesktopMgr) & vParms.vMAttrib) &&
  113.                 !((1L<<bHasExtFSVol)   & vParms.vMAttrib);
  114. }
  115.  
  116.  
  117.  
  118. static OSErr GetIconInfo (short iconType, short* rows_p, short* depth_p){
  119.     switch(iconType){
  120.         case kLargeIcon:
  121.         case kLarge4BitIcon:
  122.         case kLarge8BitIcon:
  123.             *rows_p = 32;
  124.             break;
  125.         case kSmallIcon:
  126.         case kSmall4BitIcon:
  127.         case kSmall8BitIcon:
  128.             *rows_p = 16;
  129.             break;
  130.         default:
  131.             return -1;
  132.     }
  133.     
  134.     switch(iconType){
  135.         case kLargeIcon:
  136.         case kSmallIcon:
  137.             *depth_p = 1;
  138.             break;
  139.         case kLarge4BitIcon:
  140.         case kSmall4BitIcon:
  141.             *depth_p = 4;
  142.             break;
  143.         case kLarge8BitIcon:
  144.         case kSmall8BitIcon:
  145.             *depth_p = 8;
  146.             break;
  147.     }
  148.     return noErr;
  149. }
  150.  
  151. static void FlipOne(Ptr iconBuf, short iconBufSize, short rows){
  152.     short    rowBytes    = iconBufSize/rows;
  153.     Ptr        topBufPtr    = iconBuf;
  154.     Ptr        botBufPtr    = iconBuf + iconBufSize - rowBytes;
  155.     char    rowBuf[kLarge8BitIconSize/16];
  156.     while(botBufPtr > topBufPtr){
  157.         BlockMove(topBufPtr,rowBuf,rowBytes);
  158.         BlockMove(botBufPtr,topBufPtr,rowBytes);
  159.         BlockMove(rowBuf,botBufPtr,rowBytes);
  160.         topBufPtr += rowBytes;
  161.         botBufPtr -= rowBytes;
  162.     }
  163. }
  164.  
  165. static OSErr FlipIcon(Ptr iconBuf, short iconBufSize, short iconType){
  166.     short    rows;
  167.     short    depth;
  168.     if(GetIconInfo(iconType,&rows,&depth) == noErr){
  169.         if(iconBufSize/(depth==1 ? 2 : 1) != rows*rows*depth/8){
  170.             IError(iconType,"\pFlipIcon","\pbad icon info",NULL);
  171.             return -1;
  172.         }else{
  173.             if(depth == 1){
  174.                 FlipOne(iconBuf,iconBufSize/2,rows);
  175.                 FlipOne(iconBuf + iconBufSize/2,iconBufSize/2,rows);
  176.             }else{
  177.                 FlipOne(iconBuf,iconBufSize,rows);
  178.             }
  179.         }
  180.     }
  181.     return noErr;
  182. }
  183.  
  184.  
  185. /* Flip all icons of creator from the DTDB on the specified volume */
  186. static OSErr VFlipDTDB(short vRefNum, OSType creator){
  187.     OSErr    err;
  188.     short    flipCount;
  189.     Str255    fn    = "\p";
  190.     DTPBRec    pb;
  191.     char    iconBuf[kLarge8BitIconSize];
  192.  
  193.     /* use GetPath to fill in the DTDB's refNum */
  194.     pb.ioNamePtr    = fn;
  195.     pb.ioVRefNum    = vRefNum;
  196.     if(err=PBDTGetPath(&pb)) return err;
  197.     
  198.     /* loop through & remove all creator entries */
  199.     flipCount            = 0;
  200.     pb.ioIndex            = 1;
  201.     pb.ioFileCreator    = creator;
  202.     while(PBDTGetIconInfoSync(&pb) == noErr){
  203.         pb.ioDTReqCount = pb.ioDTActCount;
  204.         pb.ioDTBuffer    = iconBuf;
  205.         if(err=PBDTGetIconSync(&pb)) return err;
  206.         if(err=FlipIcon(iconBuf,pb.ioDTActCount,pb.ioIconType)) return err;
  207.         if(err=PBDTAddIconSync(&pb)) return err;
  208.         ++flipCount;
  209.         ++pb.ioIndex;
  210.     }
  211.  
  212.     if(pb.ioResult != afpItemNotFound) return pb.ioResult;
  213.     
  214.     /* flush the DTDB if anything was flipped */
  215.     if(flipCount > 0){
  216.         if(err=PBDTFlushSync(&pb)) return err;
  217.     }
  218.     return noErr;
  219. }
  220.  
  221. OSErr FlipBNDL(FSSpecPtr spec_p){
  222.     OSErr        err;
  223.     FInfo        info;
  224.  
  225.     if(err=FSpGetFInfo(spec_p,&info)) return err;
  226.     
  227.     if(CanHackDTDB(spec_p->vRefNum)){
  228.         if(err=VFlipDTDB(spec_p->vRefNum,info.fdCreator)) return err;
  229.     }
  230.     
  231.     return noErr;
  232. }
  233.  
  234. OSErr RestartFinder(void){
  235.     OSErr    err;
  236.     FSSpec    finderSpec;
  237.  
  238.     if(err=QuitFinder(&finderSpec))        return err;
  239.     if(err=LaunchFinder(&finderSpec))    return err;
  240.  
  241.     /* Wait until we're not the FrontProcess, else we may ExitToShell before the Finder
  242.      * has fully restarted - which causes system error 41 if we are the only app running.
  243.      * Why this is, I don't know, but this seems to solve the problem.
  244.      *
  245.      * Note: we launch the finder without the launchDontSwitch flag set, so it will become
  246.      *       the front process eventually (else we'd sit around looping till the user decided
  247.      *       to click somewhere and activate the Finder)
  248.      */
  249.     {
  250.         Boolean                svabFront = true;
  251.         EventRecord            curEvent;
  252.         ProcessSerialNumber    psn;
  253.         ProcessSerialNumber    svabPsn;
  254.     
  255.         if(err=GetCurrentProcess(&svabPsn)) return err;
  256.  
  257.         while(svabFront){
  258.             WaitNextEvent(everyEvent,&curEvent,15L,0L);
  259.             if(err=GetFrontProcess(&psn)) return err;
  260.             if(err=SameProcess(&psn,&svabPsn,&svabFront)) return err;
  261.         }
  262.     }
  263.     return noErr;
  264. }
  265.  
  266.