home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / c_hfsfin.sit < prev    next >
Encoding:
Text File  |  1988-06-20  |  19.2 KB  |  660 lines

  1. 18-Jun-88 14:30:48-MDT,20286;000000000000
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:30:24 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22245; Sat, 18 Jun 88 14:30:25 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24619; Sat, 18 Jun 88 14:30:22 MDT
  8. Date: Sat, 18 Jun 88 14:30:22 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182030.AA24619@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: HFSFind.c
  13.  
  14. /* HFS recursive search desk accessory */
  15.  
  16. #include <acc.h>
  17. #include <file.h>
  18. #include <os.h>
  19. #include <win.h>
  20. #include <qdvars.h>
  21. #include <event.h>
  22. #include <te.h>
  23. #include <dialog.h>
  24. #include <control.h>
  25. #include <device.h>
  26. #include <desk.h>
  27.  
  28. ACC( 0x0400, 0, 0xfffb, 0, 9, "HFS Find " )
  29.  
  30. #define     MAXLEVEL    32    /* how deep we can go */
  31.  
  32. DialogPtr dp;                 /* modeless dialog for string selection */
  33. DialogPtr rp;                 /* modal dialog for search results */
  34. cinfopbrec  mycpb;            /* for cat info */
  35. wdpbrec     mywdpb;           /* for vref of default volume */
  36.  
  37. OSErr err;
  38. char  name[MAXLEVEL][32];           /* names of path components */
  39.  
  40. int   modkeys;                /* state of modifier keys at last event */
  41. int   OurRef;                 /* our reference number */
  42. unsigned int   resbase;       /* our first resource */ 
  43.  
  44. accopen( dctl, pb )
  45.       dctlentry *dctl;
  46.       paramblockrec *pb;
  47. {
  48.       if ( dctl->dCtlWindow == 0 )
  49.       {
  50.             GrafPtr saveport;
  51.             
  52.             GetPort(&saveport);
  53.             OurRef = dctl->dCtlRefNum;
  54.             resbase = (unsigned)0xc000 | (-32 * ( 1 + OurRef ));
  55.             dp = GetNewDialog( resbase, 0L, -1L );
  56.             ((WindowPeek)dp)->windowKind = OurRef;
  57.             rp = GetNewDialog( resbase+1, 0L, -1L );
  58.             ((WindowPeek)rp)->windowKind = OurRef;
  59.             dctl->dCtlWindow = (WindowPeek)dp;
  60.             /* activate NAME box and select SEARCH WHOLE DISK */
  61.             press(2); press(16);
  62.             SetPort(saveport);
  63.         }
  64. }
  65.  
  66. accclose( dctl, pb )
  67.       dctlentry *dctl;
  68.       paramblockrec *pb;
  69. {
  70.       DisposDialog( rp );
  71.       DisposDialog( dp );
  72.       dctl->dCtlWindow = 0;
  73.       return 0;
  74. }
  75.  
  76. accctl( dctl, pb )
  77.       dctlentry *dctl;
  78.       paramblockrec *pb;
  79. {
  80.       EventRecord *erp;
  81.       GrafPtr savedport;
  82.       DialogPtr whatDialog;
  83.       int whatItem, tf;
  84.       
  85.       GetPort( &savedport );
  86.       
  87.       switch ( pb->paramunion.CntrlParam.CSCode ) {
  88.             EventRecord event;
  89.       case accCursor:         /* make null event so that insert can flash */
  90.             event.what = 0;
  91.             DialogSelect( &event, &whatDialog, &whatItem );
  92.             break;
  93.       case accEvent:
  94.             /*
  95.              * Megamax forgot to define the long we need in the paramunion.
  96.              * Rather than add if myself, I just use diskBuff, which is
  97.              * also a long.
  98.              */
  99.             erp = (EventRecord *)(pb->paramunion.CntrlParam.csParam.diskBuff);
  100.             modkeys = erp->modifiers;
  101.             ((WindowPeek)dp)->windowKind = dialogKind;
  102.             if ( IsDialogEvent( erp ) ) {
  103.                   tf = DialogSelect( erp, &whatDialog, &whatItem );
  104.                   if ( tf && whatDialog == dp ) {
  105.                         SetPort( dp );
  106.                         press( whatItem );
  107.                   }
  108.             }
  109.             ((WindowPeek)dp)->windowKind = OurRef;
  110.                             break;
  111.       case accCut:
  112.             DlgCut( dp ); break;
  113.       case accCopy:
  114.             DlgCopy( dp ); break;
  115.       case accPaste:
  116.             DlgPaste( dp ); break;
  117.       case accClear:
  118.             dlgdelete( dp ); break;
  119.       }
  120.       SetPort( savedport );
  121. }
  122.  
  123. accprime() {}
  124. accstatus() {}
  125.  
  126.  
  127. /*********************************************************************
  128.  ***************** respond to activity in dialog *********************
  129.  *********************************************************************/
  130. press( i )
  131. {
  132.       int type;
  133.       ControlHandle item;
  134.       Rect r;
  135.       
  136.       if ( i == 1 ) {                     /* SEARCH button? */
  137.             dosearch(); return;
  138.       }
  139.       GetDItem( dp, i, &type, &item, &r );
  140.       if ( type == ChkCtrl + CtrlItem ) { /* check box ? */
  141.             type = GetCtlValue( item );
  142.             SetCtlValue( item, 1-type );
  143.             return;
  144.       }
  145.       if ( 12 <= i && i <= 15 ) {         /* type, creator, or a date ? */
  146.             if ( modkeys & 0x100 ) {      /* pretzel key pressed */
  147.                   fromfile( i );
  148.             }
  149.             return;
  150.       }
  151.       if ( i == 17 ) {                    /* CHDIR button ? */
  152.             paramblkptr pb, askfile();
  153.             if ( (pb = askfile()) == 0 )
  154.                   return;
  155.             PBSetVol( pb, FALSE );
  156.             return;
  157.       }
  158. }
  159.  
  160. fromfile( item )
  161. {
  162.       paramblkptr pb, askfile();
  163.       ControlHandle checkbox, editrecord;
  164.       Rect r; int type;
  165.       char buf[12], *cp;
  166.       unsigned long ftime;
  167.       char digit();
  168.       datetimerec dtr;
  169.       
  170.       pb = askfile();
  171.       if ( pb == 0 )
  172.             return;
  173.       switch ( item ) {
  174.       case 14:
  175.             cp = & pb->paramunion.FileParam.ioFlFndrInfo.fdCreator[0];
  176.             goto ct;
  177.       case 15:
  178.             cp = & pb->paramunion.FileParam.ioFlFndrInfo.fdType[0];
  179.       ct:
  180.             buf[0] = *cp++; buf[1] = *cp++;
  181.             buf[2] = *cp++; buf[3] = *cp++;
  182.             buf[4] = 0; break;
  183.       case 12:
  184.       case 13:
  185.             ftime = pb->paramunion.FileParam.ioFlMdDat;
  186.             Secs2Date( ftime, &dtr );
  187.             buf[0] = digit( dtr.month / 10 );
  188.             buf[1] = digit( dtr.month );
  189.             buf[2] = '/';
  190.             buf[3] = digit( dtr.day / 10 );
  191.             buf[4] = digit( dtr.day );
  192.             buf[5] = '/'; 
  193.             buf[6] = digit( dtr.year / 1000 );
  194.             buf[7] = digit( dtr.year / 100 );
  195.             buf[8] = digit( dtr.year / 10 );
  196.             buf[9] = digit( dtr.year );
  197.             buf[10] = 0;
  198.             break;
  199.       }
  200.       GetDItem( dp, item, &type, &editrecord, &r );
  201.       SetIText( editrecord, buf );
  202.       SelIText( dp, item, 0, 0 );
  203.  
  204.       DrawDialog( dp );
  205. }
  206.  
  207. char digit( num )
  208.       int num;
  209. {
  210.       return num % 10 + '0';
  211. }
  212.  
  213. /*********************************************************************
  214.  ****************************** search! ******************************
  215.  *********************************************************************/
  216.  
  217. int   targets[3][50];         /* file name patterns to search for */
  218. int   tN;                     /* true if there are some file names */
  219. long  tType;                  /* type to search for */
  220. long  tCreat;                 /* creator to search for */
  221. int   tT, tC;                 /* true if search for type, creator */
  222. unsigned long  tBefore, tAfter;     /* before and after mod times */
  223. int   tB, tA;                 /* true if search for before, after */
  224.  
  225. char scratchText[40];
  226. dosearch() {
  227.       ControlHandle checkbox, editrecord;
  228.       Rect r; int type, i;
  229.       unsigned long maketime();
  230.       
  231.       tN = 0;
  232.       for ( i = 2; i <= 4; i++ ) {
  233.             GetDItem( dp, i, &type, &checkbox, &r );
  234.             if ( GetCtlValue( checkbox ) ) {
  235.                   GetDItem( dp, i+7, &type, &editrecord, &r );
  236.                   GetIText( editrecord, scratchText );
  237.                   compile( targets[i-2], scratchText );
  238.                   tN++;
  239.             } else
  240.                   targets[i-2][0] = -10;
  241.       }
  242.       /*
  243.        * get target type and creator
  244.        */
  245.       tT = tC = 0;
  246.       GetDItem( dp, 8, &type, &checkbox, &r );
  247.       tT = GetCtlValue( checkbox );
  248.       if ( tT ) {
  249.             GetDItem( dp, 15, &type, &editrecord, &r );
  250.             GetIText( editrecord, scratchText );
  251.             tType = *(long *)scratchText;
  252.       }
  253.       GetDItem( dp, 7, &type, &checkbox, &r );
  254.       tC = GetCtlValue( checkbox );
  255.       if ( tC ) {
  256.             GetDItem( dp, 14, &type, &editrecord, &r );
  257.             GetIText( editrecord, scratchText );
  258.             tCreat = *(long *)scratchText;
  259.       }
  260.       /*
  261.        * mod time before and after
  262.        */
  263.       GetDItem( dp, 5, &type, &checkbox, &r );
  264.       tA = GetCtlValue( checkbox );
  265.       if ( tA ) {
  266.             GetDItem( dp, 12, &type, &editrecord, &r );
  267.             GetIText( editrecord, scratchText );
  268.             tAfter = maketime( scratchText );
  269.       }
  270.       GetDItem( dp, 6, &type, &checkbox, &r );
  271.       tB = GetCtlValue( checkbox );
  272.       if ( tB ) {
  273.             GetDItem( dp, 13, &type, &editrecord, &r );
  274.             GetIText( editrecord, scratchText );
  275.             tBefore = maketime( scratchText );
  276.       }
  277.       /*
  278.        * see if user want to search whole disk, and do search
  279.        */
  280.       GetDItem( dp, 16, &type, &checkbox, &r );
  281.       SearchFiles( GetCtlValue( checkbox ) );
  282. }
  283.  
  284. int AbortSearch;
  285. long eDirID[MAXLEVEL+1];
  286. int curdepth;
  287. char Volume[32];
  288. int toodeep;
  289.       
  290. SearchFiles( fromroot )
  291. {
  292.       AbortSearch = toodeep = 0;
  293.       mywdpb.ioNamePtr = Volume;
  294.       pbhgetvol( &mywdpb, FALSE );
  295.       mycpb.ioCompletion = 0;
  296.       mycpb.ioVRefNum = mywdpb.ioVRefNum;
  297.       curdepth = 0;
  298.       eDirID[0] = fromroot ? 2L : mywdpb.iowddirid;
  299.       if ( !fromroot ) 
  300.             Volume[0] = 0;
  301.       EnumerateCat();
  302.       HideWindow( rp ); SelectWindow( dp );
  303. }
  304.  
  305. long eIndex[MAXLEVEL];
  306.  
  307. EnumerateCat()
  308. {
  309. callSelf:
  310.       CheckAbort();
  311.       if ( curdepth >= MAXLEVEL ) {
  312.             if ( toodeep == 0 ) {
  313.                   NoteAlert( resbase+2, 0L );
  314.                   toodeep = 1;
  315.             }
  316.             goto retHere;
  317.       }
  318.       
  319.       if ( AbortSearch ) {
  320.             if ( AbortSearch == 2 )
  321.                   AbortSearch = 0;
  322.             if ( curdepth == 0 )
  323.                   return;
  324.             else
  325.                   goto retHere;
  326.       }
  327.       
  328.       eIndex[curdepth] = 1;
  329.       do {
  330.             mycpb.ioNamePtr = name[curdepth]; name[curdepth][0] = 0;
  331.             mycpb.ioFDirIndex = eIndex[curdepth];
  332.             mycpb.paramunion.dirinfo.iodrdirid = eDirID[curdepth];
  333.             
  334.             err = pbgetcatinfo(&mycpb,FALSE);
  335. #define FINF      paramunion.hfileinfo.ioFlFndrInfo
  336. #define TYPE      FINF.fdType
  337. #define CREAT     FINF.fdCreator
  338. #define MTIME     paramunion.hfileinfo.ioFlMdDat
  339. #define lType(x)  (*(long *)&(x.TYPE))
  340. #define lCreat(x) (*(long *)&(x.CREAT))
  341. #define lTime(x)  ((unsigned long )(x.MTIME))
  342.             if ( err == 0 ) {
  343.                   if (
  344.                         (!tN || (  matches( targets[0], name[curdepth] )
  345.                                 || matches( targets[1], name[curdepth] )
  346.                                 || matches( targets[2], name[curdepth] )
  347.                                 )
  348.                         )
  349.                   &&
  350.                         (!tT || tType == lType(mycpb))
  351.                   &&
  352.                         (!tC || tCreat == lCreat(mycpb))
  353.                   &&
  354.                         (!tA || tAfter <= lTime(mycpb))
  355.                   &&
  356.                         (!tB || tBefore >= lTime(mycpb))
  357.                   )  
  358.                         dumppath( curdepth, (int)mycpb.ioFlAttrib,
  359.                                eDirID[curdepth] );
  360.                   if ( mycpb.ioFlAttrib & 0x10 ) {
  361.                         eDirID[++curdepth] = 
  362.                               mycpb.paramunion.dirinfo.iodrdirid; 
  363.                         goto callSelf;
  364. retHere:
  365.                         --curdepth;
  366.                         err = 0;
  367.                   }
  368.                   eIndex[curdepth]++;
  369.             }
  370.       } while ( err == 0 && !AbortSearch );
  371.       if ( AbortSearch == 2 )
  372.             AbortSearch = 0;
  373.       if ( curdepth == 0 )
  374.             return;
  375.       else
  376.             goto retHere;
  377. }
  378.  
  379. char path[ 1200 ];                  /* make big enough to hold a full path
  380.                                      * spec for the longest path */
  381. dumppath( level, last, DirID )
  382.       long DirID;
  383. {
  384.       int i; char *pp, *sap();
  385.  
  386.       pp = path; *pp = 0;
  387.       if ( Volume[0] ) {
  388.             pp = sap( pp, Volume ); pp = sap( pp, ":" );
  389.       } else
  390.       if ( level || (last & 0x10) )
  391.             pp = sap( pp, ":" );
  392.       for ( i = 0; i <= level; i++ ) {
  393.             pp = sap( pp, name[i] );
  394.             pp = sap( pp, i == level ? "" : ":" );
  395.       }
  396.       sap( name[level], name[level] );
  397.       ParamText( name[level], path, (last & 0x10) ? "Dir":"File", "" );
  398.       ShowWindow( rp );
  399.       SelectWindow( rp ); DrawDialog( rp );
  400.       SetPort( rp );
  401.       
  402.       while ( 1 ) {
  403.             ((WindowPeek)rp)->windowKind = dialogKind;
  404.             ModalDialog( 0L, &i );
  405.             ((WindowPeek)rp)->windowKind = OurRef;
  406.             switch ( i ) {
  407.             case 2:
  408.                   AbortSearch = 1;  /* FALL THROUGH */
  409.             case 1:
  410.                   return; break;
  411.             case 3:
  412.                   *(long *)0x398 = DirID; break;
  413.             case 6:
  414.                    AbortSearch = 2; return;
  415.             }
  416.       }
  417. }
  418.  
  419. char * sap( str, new )
  420.       register char * str, * new;
  421. {
  422.       while ( *str++ = *new++ )
  423.             ;
  424.       return --str;
  425. }
  426.  
  427. CheckAbort() {
  428.       if ( Button() )
  429.             AbortSearch = 1;
  430. }
  431.  
  432. /*********************************************************************
  433.  ***************** file name matching with wildcards *****************
  434.  *********************************************************************/
  435.  
  436. #define     STAR        -1          /* match zero or more of anything */
  437. #define     QM          -2          /* match one of anything */
  438. #define     END         -3          /* match end of name */
  439.  
  440. #define     QUOTE       ':'         /* turn off special next character */
  441. #define     cSTAR       '*'         /* character for STAR */
  442. #define     cQM         '?'         /* character for QM */
  443. #define     cEND        '$'         /* character for END */
  444.  
  445. compile( dest, src )
  446.       register int * dest;
  447.       register char * src;
  448. {
  449.       register char cc;
  450.       
  451.       while ( 1 ) {
  452.             switch ( cc = *src++ ) {
  453.             case cSTAR:
  454.                   *dest++ = STAR; break;
  455.             case cQM:
  456.                   *dest++ = QM; break;
  457.             case cEND:
  458.                   *dest++ = (*src == '\0') ? END : cc; break;
  459.             case '\0':
  460.                   *dest++ = cc; return; break;
  461.             case QUOTE:
  462.                   if ( (*dest++ = *src++) == '\0' )
  463.                         return;
  464.                   break;
  465.             default:
  466.                   if ( 'A' <= cc && cc <= 'Z' )
  467.                         cc += 'a' - 'A';
  468.                   *dest++ = cc;
  469.             }
  470.       }
  471. }
  472.  
  473. matches( cp, np )
  474.       register  int * cp;           /* the compiled pattern to match */
  475.       register unsigned char * np;  /* the file name to check out */
  476. {
  477.       unsigned char * savenp;
  478.       int * startcp;
  479.       
  480.       savenp = np;
  481.       startcp = cp;
  482.       
  483.       while ( 1 ) {
  484.             char nc;
  485.             if ( *cp == STAR ) {
  486.                   savenp = np;            /* so we can backtrack */
  487.                   while ( *cp == STAR )
  488.                         cp++;
  489.             }
  490.             if ( *cp == '\0' )
  491.                   return 1;
  492.             if ( (nc = *np++) == '\0' )
  493.                   return (*cp == END) ? 1 : 0;
  494.             if ( 'A' <= nc && nc <= 'Z' )
  495.                   nc += 'a' - 'A';
  496.             if ( *cp++ == nc || cp[-1] == QM )
  497.                        continue;
  498.             /*
  499.              * failed to match, so we have to backtrack
  500.              */
  501.             np = savenp + 1;
  502.             while ( *--cp != STAR )
  503.                   if ( cp == startcp )
  504.                         return 0;
  505.       }
  506. }
  507.  
  508. /*********************************************************************
  509.  ******************** Interface to SFGetFile *************************
  510.  *********************************************************************/
  511.       
  512. #include <pack.h>
  513. #include <event.h>
  514.  
  515. SFReply rep;
  516. Point   corner;
  517.  
  518. /*
  519.  * whatfile gets a ref ( V or WD ) num and a name for a user selected file
  520.  */
  521. whatfile( ref, name )
  522.       int *ref;                         /* where to put reference number */
  523.       char *name;                       /* where to put name */
  524. {
  525.       boolean myfilter();
  526.  
  527.       SetPt( &corner, 70, 70 );                         /* where to put the box/
  528.       ShowCursor();                                             /* make sure us/
  529.       rep.good = 1;
  530.       SFGetFile( &corner, (char *)0, (int (*)())0, -1, "",
  531.             (char *)0, &rep );
  532.       if ( !rep.good )
  533.             return -1;
  534.       strcpy( name, rep.fName );    /* copy back name */
  535.       *ref = rep.vRefNum;           /* ...and refNum */
  536.       return 0;                                                                /
  537. }
  538.  
  539. /*
  540.  * askfile returns a paramblkptr for a user selected file
  541.  */ 
  542. paramblkptr askfile() {
  543.       int ref, err;
  544.       static paramblockrec pb;
  545.       
  546.       if ( whatfile( &ref, path ) )
  547.             return (char *)0;
  548.  
  549.       pb.ioCompletion = 0;
  550.       pb.ioNamePtr = path;
  551.       pb.ioVRefNum = ref;
  552.       pb.paramunion.FileParam.ioFVersNum = 0;
  553.       
  554.       err = PBGetFInfo( &pb, FALSE );
  555.       if ( err )
  556.             return (char *)0;
  557.       return &pb;
  558. }
  559.  
  560. /*********************************************************************
  561.  *************************** date conversion *************************
  562.  *********************************************************************/
  563.  
  564. char * getnum( cp, where )
  565.       register char *cp;
  566.       register unsigned long *where;
  567. {
  568.       for ( *where = 0; '0' <= *cp && *cp <= '9'; cp++ )
  569.             *where = *where * 10 + *cp - '0';
  570.       return cp;
  571. }
  572.  
  573. /*
  574.  * convert string to a time in seconds since Jan 1 1904.
  575.  */
  576. unsigned long maketime( cp )
  577.       register char *cp;
  578. {
  579.       long ans;
  580.       register char *tp;
  581.       
  582.       if ( *cp == '-' ) {
  583.             unsigned long relative();
  584.             return relative( ++cp );
  585.       }
  586.       
  587.       for ( tp = cp; *tp; tp++ ) {
  588.             unsigned long absdate();
  589.             if ( *tp == '/' )
  590.                   return absdate( cp );
  591.       }
  592.       
  593.       getnum( cp, &ans );      
  594.       return ans;
  595. }
  596.  
  597. /*
  598.  * Relative to now: nnD for nn days in past, nnH or nnM for
  599.  * hours or minutes
  600.  */
  601. unsigned long
  602. relative( cp )
  603.       register char *cp;
  604. {
  605.       long scale; long interval;
  606.       
  607.       cp = getnum( cp, &interval );
  608.       switch ( *cp ) {
  609.       default: case 'd': case 'D':  scale = 86400; break;
  610.       case 'h': case 'H':           scale = 3600; break;
  611.       case 'm': case 'M':           scale = 60; break;
  612.       }
  613.       return *(unsigned long *)0x20c - scale * interval;
  614. }
  615.  
  616. /*
  617.  * date is MM/DD/YY or MM/DD/YYYY
  618.  */
  619. unsigned long absdate( cp )
  620.       register char *cp;
  621. {
  622.       unsigned long month = 0, day = 0, year = 0;
  623.       datetimerec dtr; unsigned long secs;
  624.       
  625.       cp = getnum( cp, &month );
  626.       if ( *cp++ != '/' )
  627.             return 0L;
  628.       cp = getnum( cp, &day );
  629.       if ( *cp++ != '/' )
  630.             return 0L;
  631.       cp = getnum( cp, &year );
  632.       if ( month < 1 || month > 12 )
  633.             return 0L;
  634.       if ( year < 1900 )
  635.             year += 1900;
  636.       dtr.year = year;
  637.       dtr.month = month;
  638.       dtr.day = day;
  639.       dtr.hour = dtr.minute = dtr.second = 0;
  640.       Date2Secs( &dtr, &secs );
  641.       return secs;
  642. }
  643.  
  644. /*********************************************************************
  645.  ********************** print debugging info *************************
  646.  *********************************************************************/
  647.  
  648. #ifdef APRINT
  649. #define     STOPALERT   12346 /* alert for errors */
  650.  
  651. aprintf( fmt, a1, a2, a3, a4, a5, a6 )
  652.       char *fmt;
  653. {
  654.       char buf[200];
  655.       sprintf( buf, fmt, a1, a2, a3, a4, a5, a6 );
  656.       ParamText( buf, "", "", "" );
  657.       StopAlert( STOPALERT, 0L );
  658. }
  659. #endif
  660.