[net.sources.mac] HFS Find

tim@ism780c.UUCP (Tim Smith) (10/11/86)

Here is a DA that allows you to search an HFS volume for files
by name ( with wildcards ), mod. date, type, or creator.  For
each matching file or directory you are given the option to
continue the search, stop, skip the directory, or set the
standard file directory.  You are also shown the full path
name of the file.

Included in the following shar archive are the DA in .hqx
format, the source in Megamax C, and the instructions.  Please
read the instructions before using the DA.

: -------------------- cut here -----------------------------
#
#
# This is a shar archive.  Extract with sh, not csh
#
# This archive contains the following files:
#
#   hfsfda.c
#   hfsfda.doc
#   hfsfda.hqx
#
# Note: if you have checksum problems, see if the CSUM variable is
# being set to something reasonable for your system.
#
CSUM=${SUM:-"sum -r"}
echo extract hfsfda.c...
sed 's/^X//' > hfsfda.c <<'---EOF-EOT-M-O-U-S-E---'
X#include <acc.h>
X#include <file.h>
X#include <os.h>
X#include <win.h>
X#include <qdvars.h>
X#include <event.h>
X#include <te.h>
X#include <dialog.h>
X#include <control.h>
X#include <device.h>
X#include <desk.h>
X
X/* Copyright 1986 by Coyote Systems
X *
X * This may be freely distributed, and code fragments
X * extracted for use in other programs.
X *
X * This is written in Megamax C
X */
X
XACC( 0x0400, 0, 0xfffb, 0, 9, "HFS Find " )
X
X#define     MAXLEVEL    32    /* how deep we can go */
X
XDialogPtr dp;                 /* modeless dialog for string selection */
XDialogPtr rp;                 /* modal dialog for search results */
Xcinfopbrec  mycpb;            /* for cat info */
Xwdpbrec     mywdpb;           /* for vref of default volume */
X
XOSErr err;
Xchar  name[MAXLEVEL][32];           /* names of path components */
X
Xint   modkeys;                /* state of modifier keys at last event */
Xint   OurRef;                 /* our reference number */
Xunsigned int   resbase;       /* our first resource */ 
X
Xaccopen( dctl, pb )
X      dctlentry *dctl;
X      paramblockrec *pb;
X{
X      if ( dctl->dCtlWindow == 0 )
X      {
X            GrafPtr saveport;
X            
X            GetPort(&saveport);
X            OurRef = dctl->dCtlRefNum;
X            resbase = (unsigned)0xc000 | (-32 * ( 1 + OurRef ));
X            dp = GetNewDialog( resbase, 0L, -1L );
X            ((WindowPeek)dp)->windowKind = OurRef;
X            dctl->dCtlWindow = (WindowPeek)dp;
X            /* activate NAME box and select SEARCH WHOLE DISK */
X            press(2); press(16);
X            SetPort(saveport);
X     	}
X}
X
Xaccclose( dctl, pb )
X      dctlentry *dctl;
X      paramblockrec *pb;
X{
X      if ( dctl->dCtlWindow ) {
X            DisposDialog( dp );
X            dctl->dCtlWindow = 0;
X      }
X      return 0;
X}
X
Xaccctl( dctl, pb )
X      dctlentry *dctl;
X      paramblockrec *pb;
X{
X      EventRecord *erp;
X      GrafPtr savedport;
X      DialogPtr whatDialog;
X      int whatItem, tf;
X      
X      GetPort( &savedport );
X      
X      switch ( pb->paramunion.CntrlParam.CSCode ) {
X            EventRecord event;
X      case accCursor:         /* make null event so that insert can flash */
X            event.what = 0;
X            DialogSelect( &event, &whatDialog, &whatItem );
X            break;
X      case accEvent:
X            /*
X             * Megamax forgot to define the long we need in the paramunion.
X             * Rather than add if myself, I just use diskBuff, which is
X             * also a long.
X             */
X            erp = (EventRecord *)(pb->paramunion.CntrlParam.csParam.diskBuff);
X            modkeys = erp->modifiers;
X            ((WindowPeek)dp)->windowKind = dialogKind;
X            if ( IsDialogEvent( erp ) ) {
X                  tf = DialogSelect( erp, &whatDialog, &whatItem );
X                  if ( tf && whatDialog == dp ) {
X                        SetPort( dp );
X                        press( whatItem );
X                  }
X            }
X            ((WindowPeek)dp)->windowKind = OurRef;
X     			    break;
X      case accCut:
X            DlgCut( dp ); break;
X      case accCopy:
X            DlgCopy( dp ); break;
X      case accPaste:
X            DlgPaste( dp ); break;
X      case accClear:
X            dlgdelete( dp ); break;
X      }
X      SetPort( savedport );
X}
X
Xaccprime() {}
Xaccstatus() {}
X
X
X/*********************************************************************
X ***************** respond to activity in dialog *********************
X *********************************************************************/
Xpress( i )
X{
X      int type;
X      ControlHandle item;
X      Rect r;
X      
X      if ( i == 1 ) {                     /* SEARCH button? */
X            dosearch(); return;
X      }
X      GetDItem( dp, i, &type, &item, &r );
X      if ( type == ChkCtrl + CtrlItem ) { /* check box ? */
X            type = GetCtlValue( item );
X            SetCtlValue( item, 1-type );
X            return;
X      }
X      if ( 12 <= i && i <= 15 ) {         /* type, creator, or a date ? */
X            if ( modkeys & 0x100 ) {      /* pretzel key pressed */
X                  fromfile( i );
X            }
X            return;
X      }
X      if ( i == 17 ) {                    /* CHDIR button ? */
X            paramblkptr pb, askfile();
X            if ( (pb = askfile()) == 0 )
X                  return;
X            PBSetVol( pb, FALSE );
X            return;
X      }
X}
X
Xfromfile( item )
X{
X      paramblkptr pb, askfile();
X      ControlHandle checkbox, editrecord;
X      Rect r; int type;
X      char buf[18], *cp;
X      unsigned long ftime;
X      char digit();
X      datetimerec dtr;
X      
X      pb = askfile();
X      if ( pb == 0 )
X            return;
X      switch ( item ) {
X      case 14:
X            cp = & pb->paramunion.FileParam.ioFlFndrInfo.fdCreator[0];
X            goto ct;
X      case 15:
X            cp = & pb->paramunion.FileParam.ioFlFndrInfo.fdType[0];
X      ct:
X            buf[0] = *cp++; buf[1] = *cp++;
X            buf[2] = *cp++; buf[3] = *cp++;
X            buf[4] = 0; break;
X      case 12:
X      case 13:
X            ftime = pb->paramunion.FileParam.ioFlMdDat;
X            Secs2Date( ftime, &dtr );
X            buf[0] = digit( dtr.month / 10 );
X            buf[1] = digit( dtr.month );
X            buf[2] = '/';
X            buf[3] = digit( dtr.day / 10 );
X            buf[4] = digit( dtr.day );
X            buf[5] = '/'; 
X            buf[6] = digit( dtr.year / 1000 );
X            buf[7] = digit( dtr.year / 100 );
X            buf[8] = digit( dtr.year / 10 );
X            buf[9] = digit( dtr.year );
X            buf[10] = ' ';
X            buf[11] = digit( dtr.hour / 10 );
X            buf[12] = digit( dtr.hour );
X            buf[13] = ':';
X            buf[14] = digit( dtr.minute / 10 );
X            buf[15] = digit( dtr.minute );
X            buf[16] = '\0';
X            break;
X      }
X      GetDItem( dp, item, &type, &editrecord, &r );
X      SetIText( editrecord, buf );
X      SelIText( dp, item, 0, 0 );
X
X      DrawDialog( dp );
X}
X
Xchar digit( num )
X      int num;
X{
X      return num % 10 + '0';
X}
X
X/*********************************************************************
X ****************************** search! ******************************
X *********************************************************************/
X
Xint   targets[3][50];         /* file name patterns to search for */
Xint   tN;                     /* true if there are some file names */
Xlong  tType;                  /* type to search for */
Xlong  tCreat;                 /* creator to search for */
Xint   tT, tC;                 /* true if search for type, creator */
Xunsigned long  tBefore, tAfter;     /* before and after mod times */
Xint   tB, tA;                 /* true if search for before, after */
X
Xchar scratchText[40];
Xdosearch() {
X      ControlHandle checkbox, editrecord;
X      Rect r; int type, i;
X      unsigned long maketime();
X      
X      tN = 0;
X      for ( i = 2; i <= 4; i++ ) {
X            GetDItem( dp, i, &type, &checkbox, &r );
X            if ( GetCtlValue( checkbox ) ) {
X                  GetDItem( dp, i+7, &type, &editrecord, &r );
X                  GetIText( editrecord, scratchText );
X                  compile( targets[i-2], scratchText );
X                  tN++;
X            } else
X                  targets[i-2][0] = -10;
X      }
X      /*
X       * get target type and creator
X       */
X      tT = tC = 0;
X      GetDItem( dp, 8, &type, &checkbox, &r );
X      tT = GetCtlValue( checkbox );
X      if ( tT ) {
X            GetDItem( dp, 15, &type, &editrecord, &r );
X            GetIText( editrecord, scratchText );
X            tType = *(long *)scratchText;
X      }
X      GetDItem( dp, 7, &type, &checkbox, &r );
X      tC = GetCtlValue( checkbox );
X      if ( tC ) {
X            GetDItem( dp, 14, &type, &editrecord, &r );
X            GetIText( editrecord, scratchText );
X            tCreat = *(long *)scratchText;
X      }
X      /*
X       * mod time before and after
X       */
X      GetDItem( dp, 5, &type, &checkbox, &r );
X      tA = GetCtlValue( checkbox );
X      if ( tA ) {
X            GetDItem( dp, 12, &type, &editrecord, &r );
X            GetIText( editrecord, scratchText );
X            tAfter = maketime( scratchText );
X      }
X      GetDItem( dp, 6, &type, &checkbox, &r );
X      tB = GetCtlValue( checkbox );
X      if ( tB ) {
X            GetDItem( dp, 13, &type, &editrecord, &r );
X            GetIText( editrecord, scratchText );
X            tBefore = maketime( scratchText );
X      }
X      /*
X       * see if user want to search whole disk, and do search
X       */
X      GetDItem( dp, 16, &type, &checkbox, &r );
X      SearchFiles( GetCtlValue( checkbox ) );
X}
X
Xint AbortSearch;
Xlong eDirID[MAXLEVEL+1];
Xint curdepth;
Xchar Volume[32];
Xint toodeep;
X      
XSearchFiles( fromroot )
X{
X      AbortSearch = toodeep = 0;
X      mywdpb.ioNamePtr = Volume;
X      pbhgetvol( &mywdpb, FALSE );
X      mycpb.ioCompletion = 0;
X      mycpb.ioVRefNum = mywdpb.ioVRefNum;
X      curdepth = 0;
X      eDirID[0] = fromroot ? 2L : mywdpb.iowddirid;
X      if ( !fromroot ) 
X            Volume[0] = 0;
X      rp = GetNewDialog( resbase+1, 0L, -1L );
X      EnumerateCat();
X      HideWindow( rp ); SelectWindow( dp );
X      DisposDialog( rp );
X}
X
Xlong eIndex[MAXLEVEL];
X
XEnumerateCat()
X{
XcallSelf:
X      CheckAbort();
X      if ( curdepth >= MAXLEVEL ) {
X            if ( toodeep == 0 ) {
X                  NoteAlert( resbase+2, 0L );
X                  toodeep = 1;
X            }
X            goto retHere;
X      }
X      
X      if ( AbortSearch ) {
X            if ( AbortSearch == 2 )
X                  AbortSearch = 0;
X            if ( curdepth == 0 )
X                  return;
X            else
X                  goto retHere;
X      }
X      
X      eIndex[curdepth] = 1;
X      do {
X            mycpb.ioNamePtr = name[curdepth]; name[curdepth][0] = 0;
X            mycpb.ioFDirIndex = eIndex[curdepth];
X            mycpb.paramunion.dirinfo.iodrdirid = eDirID[curdepth];
X            
X            err = pbgetcatinfo(&mycpb,FALSE);
X#define FINF      paramunion.hfileinfo.ioFlFndrInfo
X#define TYPE      FINF.fdType
X#define CREAT     FINF.fdCreator
X#define MTIME     paramunion.hfileinfo.ioFlMdDat
X#define lType(x)  (*(long *)&(x.TYPE))
X#define lCreat(x) (*(long *)&(x.CREAT))
X#define lTime(x)  ((unsigned long )(x.MTIME))
X            if ( err == 0 ) {
X                  if (
X                        (!tN || (  matches( targets[0], name[curdepth] )
X                                || matches( targets[1], name[curdepth] )
X                                || matches( targets[2], name[curdepth] )
X                                )
X                        )
X                  &&
X                        (!tT || tType == lType(mycpb))
X                  &&
X                        (!tC || tCreat == lCreat(mycpb))
X                  &&
X                        (!tA || tAfter <= lTime(mycpb))
X                  &&
X                        (!tB || tBefore >= lTime(mycpb))
X                  )  
X                        dumppath( curdepth, (int)mycpb.ioFlAttrib,
X                               eDirID[curdepth] );
X                  if ( mycpb.ioFlAttrib & 0x10 ) {
X                        eDirID[++curdepth] = 
X                              mycpb.paramunion.dirinfo.iodrdirid; 
X                        goto callSelf;
XretHere:
X                        --curdepth;
X                        err = 0;
X                  }
X                  eIndex[curdepth]++;
X            }
X      } while ( err == 0 && !AbortSearch );
X      if ( AbortSearch == 2 )
X            AbortSearch = 0;
X      if ( curdepth == 0 )
X            return;
X      else
X            goto retHere;
X}
X
Xchar path[ 1200 ];                  /* make big enough to hold a full path
X                                     * spec for the longest path */
Xdumppath( level, last, DirID )
X      long DirID;
X{
X      int i; char *pp, *sap();
X
X      pp = path; *pp = 0;
X      if ( Volume[0] ) {
X            pp = sap( pp, Volume ); pp = sap( pp, ":" );
X      } else
X      if ( level || (last & 0x10) )
X            pp = sap( pp, ":" );
X      for ( i = 0; i <= level; i++ ) {
X            pp = sap( pp, name[i] );
X            pp = sap( pp, i == level ? "" : ":" );
X      }
X      sap( name[level], name[level] );
X      ParamText( name[level], path, (last & 0x10) ? "Dir":"File", "" );
X      ShowWindow( rp );
X      SelectWindow( rp ); DrawDialog( rp );
X      SetPort( rp );
X      
X      while ( 1 ) {
X            ModalDialog( 0L, &i );
X            switch ( i ) {
X            case 2:
X                  AbortSearch = 1;  /* FALL THROUGH */
X            case 1:
X                  return; break;
X            case 3:
X                  *(long *)0x398 = DirID; break;
X            case 6:
X                   AbortSearch = 2; return;
X            }
X      }
X}
X
Xchar * sap( str, new )
X      register char * str, * new;
X{
X      while ( *str++ = *new++ )
X            ;
X      return --str;
X}
X
XCheckAbort() {
X      if ( Button() )
X            AbortSearch = 1;
X}
X
X/*********************************************************************
X ***************** file name matching with wildcards *****************
X *********************************************************************/
X 
X#define     STAR        -1          /* match zero or more of anything */
X#define     QM          -2          /* match one of anything */
X#define     END         -3          /* match end of name */
X
X#define     QUOTE       ':'         /* turn off special next character */
X#define     cSTAR       '*'         /* character for STAR */
X#define     cQM         '?'         /* character for QM */
X#define     cEND        '$'         /* character for END */
X
Xcompile( dest, src )
X      register int * dest;
X      register char * src;
X{
X      register char cc;
X      
X      while ( 1 ) {
X            switch ( cc = *src++ ) {
X            case cSTAR:
X                  *dest++ = STAR; break;
X            case cQM:
X                  *dest++ = QM; break;
X            case cEND:
X                  *dest++ = (*src == '\0') ? END : cc; break;
X            case '\0':
X                  *dest++ = cc; return; break;
X            case QUOTE:
X                  if ( (*dest++ = *src++) == '\0' )
X                        return;
X                  break;
X            default:
X                  if ( 'A' <= cc && cc <= 'Z' )
X                        cc += 'a' - 'A';
X                  *dest++ = cc;
X            }
X      }
X}
X
Xmatches( cp, np )
X      register  int * cp;           /* the compiled pattern to match */
X      register unsigned char * np;  /* the file name to check out */
X{
X      unsigned char * savenp;
X      int * startcp;
X      
X      savenp = np;
X      startcp = cp;
X      
X      while ( 1 ) {
X            char nc;
X            if ( *cp == STAR ) {
X                  savenp = np;            /* so we can backtrack */
X                  while ( *cp == STAR )
X                        cp++;
X            }
X            if ( *cp == '\0' )
X                  return 1;
X            if ( (nc = *np++) == '\0' )
X                  return (*cp == END) ? 1 : 0;
X            if ( 'A' <= nc && nc <= 'Z' )
X                  nc += 'a' - 'A';
X            if ( *cp++ == nc || cp[-1] == QM )
X                       continue;
X            /*
X             * failed to match, so we have to backtrack
X             */
X            np = savenp + 1;
X            while ( *--cp != STAR )
X                  if ( cp == startcp )
X                        return 0;
X      }
X}
X
X/*********************************************************************
X ******************** Interface to SFGetFile *************************
X *********************************************************************/
X      
X#include <pack.h>
X#include <event.h>
X
XSFReply rep;
XPoint	corner;
X
X/*
X * whatfile gets a ref ( V or WD ) num and a name for a user selected file
X */
Xwhatfile( ref, name )
X      int *ref;  			/* where to put reference number */
X      char *name;			/* where to put name */
X{
X      boolean myfilter();
X
X      SetPt( &corner, 70, 70 );    			/* where to put the box */
X      ShowCursor();    						/* make sure user can point */
X      rep.good = 1;
X      SFGetFile( &corner, (char *)0, (int (*)())0, -1, "",
X            (char *)0, &rep );
X      if ( !rep.good )
X            return -1;
X      strcpy( name, rep.fName );    /* copy back name */
X      *ref = rep.vRefNum;           /* ...and refNum */
X      return 0;  							            /* OK */
X}
X
X/*
X * askfile returns a paramblkptr for a user selected file
X */ 
Xparamblkptr askfile() {
X      int ref, err;
X      static paramblockrec pb;
X      
X      if ( whatfile( &ref, path ) )
X            return (char *)0;
X
X      pb.ioCompletion = 0;
X      pb.ioNamePtr = path;
X      pb.ioVRefNum = ref;
X      pb.paramunion.FileParam.ioFVersNum = 0;
X      
X      err = PBGetFInfo( &pb, FALSE );
X      if ( err )
X            return (char *)0;
X      return &pb;
X}
X
X/*********************************************************************
X *************************** date conversion *************************
X *********************************************************************/
X 
Xchar * getnum( cp, where )
X      register char *cp;
X      register unsigned long *where;
X{
X      for ( *where = 0; '0' <= *cp && *cp <= '9'; cp++ )
X            *where = *where * 10 + *cp - '0';
X      return cp;
X}
X
Xchar *
Xgetmdy( cp, mp, dp, yp )
X      char * cp;
X      unsigned long *mp, *dp, *yp;
X{
X      cp = getnum( cp, mp );
X      if ( *cp++ != '/' )
X            return --cp;
X      cp = getnum( cp, dp );
X      if ( *cp++ != '/' )
X            return --cp;
X      cp = getnum( cp, yp );
X      if ( *yp < 1900 )
X            *yp += 1900;
X}
X
Xchar *
Xgethm( cp, hp, mp )
X      char * cp;
X      unsigned long *hp, *mp;
X{
X      cp = getnum( cp, hp );
X      if ( *cp++ != ':' )
X            return --cp;
X      cp = getnum( cp, mp );
X      return cp;
X}
X
X/*
X * convert string to a time in seconds since Jan 1 1904.
X */
Xunsigned long maketime( cp )
X      register char *cp;
X{
X      long ans;
X      register char *tp;
X      
X      if ( *cp == '-' ) {
X            unsigned long relative();
X            return relative( ++cp );
X      }
X      
X      for ( tp = cp; *tp; tp++ ) {
X            unsigned long absdate();
X            if ( *tp == '/' || *tp == ':' )
X                  return absdate( cp );
X      }
X      
X      getnum( cp, &ans );      
X      return ans;
X}
X
X/*
X * Relative to now: nnD for nn days in past, nnH or nnM for
X * hours or minutes
X */
Xunsigned long
Xrelative( cp )
X      register char *cp;
X{
X      long scale; long interval;
X      
X      cp = getnum( cp, &interval );
X      switch ( *cp ) {
X      default: case 'd': case 'D':  scale = 86400; break;
X      case 'h': case 'H':           scale = 3600; break;
X      case 'm': case 'M':           scale = 60; break;
X      }
X      return *(unsigned long *)0x20c - scale * interval;
X}
X
X/*
X * date is PART or PART PART, where PART is one of HH:MM, MM/DD, MM/DD/YY
X * or MM/DD/YY.
X */
Xunsigned long absdate( cp )
X      register char *cp;
X{
X      unsigned long month, day, year, hour, minute;
X      datetimerec dtr; unsigned long secs;
X      char * tp;
X      
X      year = month = minute = 0xfeedabad;       /* illegal values */
X      
X      for ( secs = 0; secs < 2; secs++ ) {
X            while ( *cp ) {
X                  if ( '0' <= *cp && *cp <= '9' ) {
X                        for ( tp = cp; *tp != '/' && *tp != ':' ; tp++ )
X                              if ( *tp == '\0' )
X                                    break;
X                        if ( *tp != '\0' )
X                              if (*tp == '/')
X                                    cp = getmdy( cp, &month, &day, &year );
X                              else
X                                    cp = gethm( cp, &hour, &minute );
X                        break;
X                  } else
X                        cp++;
X            }
X      }
X      Secs2Date( *(unsigned long *)0x20c, &dtr );     /* get defaults */
X      dtr.second = 0;
X      if ( month != 0xfeedabad ) {
X            dtr.hour = dtr.minute = 0;
X            if ( year != 0xfeedabad )
X                  dtr.year = year;
X            dtr.month = month;
X            dtr.day = day;
X      }
X      if ( minute != 0xfeedabad ) {
X            dtr.minute = minute;
X            dtr.hour = hour;
X      }
X      Date2Secs( &dtr, &secs );
X      return secs;
X}
X/*********************************************************************
X ********************** print debugging info *************************
X *********************************************************************/
X
X#ifdef APRINT
X#define     STOPALERT   12346 /* alert for errors */
X
Xaprintf( fmt, a1, a2, a3, a4, a5, a6 )
X      char *fmt;
X{
X      char buf[200];
X      sprintf( buf, fmt, a1, a2, a3, a4, a5, a6 );
X      ParamText( buf, "", "", "" );
X      StopAlert( STOPALERT, 0L );
X}
X#endif
X             
X                  
---EOF-EOT-M-O-U-S-E---
set FOO `$CSUM hfsfda.c`
if [ X$2 != X10090 ]
then
    echo bad checksum: hfsfda.c
fi
echo extract hfsfda.doc...
sed 's/^X//' > hfsfda.doc <<'---EOF-EOT-M-O-U-S-E---'
XThese instructions are for HFS Find version 1.2
X
XIntroduction
X
X    HFS Find searches an HFS volume for files.  You may limit the search to
X    files that have a particular name, creator, type, or modification date, or
X    that reside under a specific folder.
X
XUsing HFS Find
X
X    When you open HFS Find, a window appears.  This window contains
X    seven boxes for entering text, eight check buttons, and two push
X    buttons.
X
X    The seven text boxes are used to tell HFS Find what files you want
X    to search for.  Each of these is associated with a check button,
X    which is located to the left of the text box.  When the check button
X    is checked, the text box is ACTIVE, which means that HFS Find will
X    use the text in the box to determine what files to show.  When the
X    check button is not checked, the text box is INACTIVE.  HFS Find
X    ignores the contents of inactive text boxes.
X
X    The top two text boxes are used to hold a file type and a file
X    creator.  The next two are used to hold modification dates.  The
X    final three are used to hold file names.
X
X    A file will be shown if all of the following conditions are true:
X
X        Either the "creator" box is inactive, or the file creator matches
X        the contents of the "creator" box.
X
X        Either the "type" box is inactive, or the file type matches
X        the contents of the "type" box.
X
X        Either the "Older than" box is inactive, or the modification date
X        of the file is earlier than the date in the "Older than" box.
X
X        Either the "Newer than" box is inactive, or the modification date
X        of the file is later than the date in the "Newer than" box.
X
X        Either all the "name" boxes are inactive, or the file name matches
X        the contents of one of the active "name" boxes.  It doesn't have
X        to match exactly.  See below for more information.
X
X    The check button labeled "Search whole disk" controls where HFS Find
X    looks.  If the button is checked, HFS Find will search the entire
X    volume.  When the button is unchecked, HFS Find will only look at
X    files and folders under the current folder.
X
X    You may set the current folder by pressing the "Search From" button.
X    You select a file in the folder you wish to start searching from.
X    ( There is currently no way to select a folder directly.  If the
X    folder you want to start searching from contains only other folders,
X    there is no way to restrict the search to just that folder.  Sorry. )
X
X    Finally, to actually start a search, press the "Do Search!" button.
X
XResults
X
X    When HFS Find finds a file or folder that satisfies the conditions
X    you specified, it will present a dialog.  At the top of the dialog
X    will be the name of the file or directory.  Below this is the path
X    name.  The path will be from the root of the volume if you searched
X    the entire volume, and from the current folder if you didn't.
X
X    There are four buttons in the dialog.  The "Cancel Search" button
X    cancels the search.  The "Continue Search" button continues the
X    search.
X
X    The "Skip Folder" button does one of two things.  If the file being
X    shown is a folder, then "Skip Folder" causes the search to be
X    resumed, but to skip any files contained in that folder.  If the
X    file being shown is not a folder, then "Skip Folder" causes the
X    search to continue, but to not show any more files from the folder
X    that this file is in.
X
X    The last button, "Set Standard File Folder", sets the folder that the
X    standard file package uses to be the folder that the file or folder
X    shown is contained in.  When you select OPEN or SAVE AS from the FILE
X    menu in most applications, this is the folder that the OPEN or
X    SAVE AS dialog will start in.
X
XStopping a Search
X
X    Press and hold the mouse button down during a search to abort.
X
XMatching Names
X
X    A file name matches the contents of a name box if the file name
X    starts with the characters in the name box.  For example, a name
X    box that contains "abc" would match files "abc", "abcd", but not
X    "ab".
X
X    Four characters have special meaning in a name box.  "?" matches
X    with any single character of the file name.  "*" matches any
X    number of characters from the file name ( including zero characters ).
X    A "$" at the end of a name box matches the end of a file name.
X    Finally, ":" followed by another character matches that other
X    character.
X
X    Here are some examples:
X        "*.h$" would match all files that end with ".h".  "*.h" would
X        match all files that have ".h" anywhere in their name.  "a*b?c*d?$"
X        would match all files whose name starts with an "a", has a "b" two
X        characters before a "c", and somewhere after the "c", has a "d",
X        one more character, and then ends.  Note that it would NOT match
X        a file named "abdc", because the "d" can not be used to match both
X        "b?c" and "d?".  
X
XDates
X
X	The two boxes that accept dates accept three formats.  The first
X    consists of a date and time.  The date is either MONTH/DAY or
X    MONTH/DAY/YEAR, where MONTH is a number from 1 to 12, DAY is a
X    number from 1 to 31, and YEAR is the year.  If YEAR is less than
X    1900, 1900 is added.  If you use the MONTH/DAY from then the year
X    will be the current year.  The time is HOUR:MINUTE, where HOUR is
X    a number from 0 to 23, and MINUTE is from 0 to 59.  The time may
X    either come before or after the date.  Seperate the time and date
X    with a space.
X
X    If you give a date but no time, the time is 00:00.  If you give
X    a time but no date, the date is the date you next press "Do Search!"
X
X    For example, if the current date is 9/23/86, the following would
X    all be valid ways to specify 3:30 PM on 9/23/86: "15:30", "15:30 9/23",
X    "9/23/1986 15:30", "9/23/86 15:30".
X
X	You may instead specify the number of minutes, hours, or days before
X    the current date and time.  You do this be entering a minus sign,
X    the number of mintues, hours, or days, and an M, H, or D ( or m, h, or
X    d ).  For example, -12h would mean 12 hours before the time the
X    "Do Search!" button is pressed.  -7D would mean 7 days.
X
X    You may also simply specify the number of seconds since Jan 1, 1904
X    ( let's hear it for useless features! )
X
XAnother Way to Enter Things in the Type, Creator, and Date Boxes.
X
X    If you press the command key and click the mouse button in one of
X    these boxes, you will be presented with a dialog that lets
X    you select a file.  The type, creator, or date will be set to
X    match the file you select.
X
XAn Example
X
X    We desire to find all MacWrite files whose name starts with "Report"
X    or "Chapter".
X
X    Type "macwrite" into a name box.  Make that the only active box.  We
X    then search the whole disk to find MacWrite.  When we find it, we
X    press "Set SFGetFile directory", and then "Cancel Search".
X
X    Now we command click in the "creator" box.  We select MacWrite from
X    the list of files shown.  "MACA" appears in the "creator" box.
X
X    Enter "report" in a name box, and "chapter" in another name box.
X    Make those name boxes active.  Also make the creator box active.
X    Press "Do Search".
X
XAnother Example
X
X    We want to decide if it is time to do a backup of our hard disk.
X    We did our last backup 7 days ago.
X
X    Open HFS Find.  Type "-8d" ( eight rather than seven to be safe )
X    into the "Newer than" box.  Activate it by checking it's check box.
X
X    Deactivate all the other boxes.  Make sure "Search whole disk" is
X    checked.
X
X    Press search.
X
X    You will see all files you have diddled with since your backup.
X
XProgram Limits
X
X    Folders more than 32 levels below the folder the search starts in
X    will be skipped.  You will be told when HFS Find is going to have
X    to skip some folders.
X
X    The path name for a file can not exceed about 1200 characters.  If
X    it does, the world will end.  You should hit the depth limit before
X    you hit this one.
X
X    No text box should contain more than about 35 characters.
X
X    HFS Find *seems* to work on MFS volumes also, although it was not
X    meant to do so.  That it does may be considered an accident.
---EOF-EOT-M-O-U-S-E---
set FOO `$CSUM hfsfda.doc`
if [ X$2 != X49529 ]
then
    echo bad checksum: hfsfda.doc
fi
echo extract hfsfda.hqx...
sed 's/^X//' > hfsfda.hqx <<'---EOF-EOT-M-O-U-S-E---'
X(This file must be converted with BinHex 4.0)
X
X:#dK'8b"'D@jN)%4"!%4'58a%68p@!*!)(k,&EJ#3"!%!N!-Hm3!!(I%!N!1aF'*
XeEQa[BfYbB3S+F'*cCA4MBA4TEJT`G'pMFh4b#Q-)5%C6)%CTEQ4Z!J#30jZJmB%
X!N!BISJS+Af*TEQ&NC!TIBQPZBA*j#JTIBQPZFQ9Y#PpLD@jKFRN+#PpLD@jdFh3
X+Af*TEQ&bH3S+Eh"PEJTRCA4bC@CZG@d+Cf9dC'PbD@3+CA*bEQm+Af*TEQ&NC!T
X33Np`C@i+F'*SEh"PEJS+D@jTG#j[#JS!!5%J!!4ID@jTG!S+Af%!N!--!%S!2!#
XZ!F6"JN4%!!!"K!!4!*!&D!$!!*!!!4J%#N4[)&0PBA*MD#%!N!93!!J!B!!F"3#
X3"QJ!#!"i!"`&!*!'J!!)!*!!!"`&!*!'1!!)!%J!F!8,6Q9hCA)J9'KKEMS!N!B
XJ!!J!-!"`"3dJ)%pXC'9b)&4SB@ik#!#3"3J!Q!!B!1!&#%0bC@&dEh)k!*!&#!!
X)!"J!3!8&9(P`C6UB!*!&8!!J!'!!X"!&EQ&YC6m!N!CS!#!!H!#`%!#3"S!!)!#
X3!!#`%!#3"MJ!H!")!4J3#LdMC#"[FL!Y)fJ!N!8J!(J!-!%B%!KYE5pNC#pjH3#
X3"3J!k!!B!4J3!*!'#!")!"J!H"!!N!DB!!J!U!#B"4&6C@&bBfJJGfK[E'8JC'P
XcDf3!N!93!-!!B!%B"!Y6C@&bBfJJ4R*[E8B!N!@`!#J!`!%)#"e@-5ib)+NJ-6N
Xi0L"LH5"$EhP[G'8J8hPcG'9YFh3!N!2-!!8!N!9i!'J!N!!!k!323fpZG'PZG@8
XJ8f9KFQ0S%3#3"9J!#!"`!*!!"!e$B@jMC@`J8f9KFQ0SP!#3"AJ!m!#3!!'B""K
X6CA3J8h4KEQ4KFQ3J4QPXC5"'EfaNCA)!N!8)!!J!53'A#"*H-L!p)&i`$9"KG'J
XJ25"H-3d!N!9B!*J!F!'B##*3FQ9cFb"YEh9cC5"NGA*TEQFJFf9KFQ0S)(4[)'&
XLEh*d!*!&H!!)!*!!!'!%#e0VDA!J4QpXC'9b%J#3!i`!!3#3"8!!F!"B!9J%)P0
XVDA!JC'PbC@0dEh*TCA-JG'KKG#"KFQ8JG'p[)'4PCA!!N!83!&!!1!'!L%Y$BA"
XdB@PZ)5!J9'KP)&0PBA*MD#""E'G[FQPdD'dK)#"*G#"MB@jZB5"SB@jNE'8JFh9
XLC'PbC@0dEh*TCA-JG'KTFb"NC@9`)5!!N!3L!%%!F!%6!CF!N!3"!*!&`B!04QP
XZC#")4P-J4QPXC3#3!am!3!!a!0i"c`!"!*!)`B%+6Q9h)%4TB@a[C`#3!aBk!$S
X!N!-k!%4TFJ"'D@aP!*!)'T)%!*!$rrX!!"Fm'&iBF"L#'*3*5%C6)%CTEQ3J6PE
Xrr#"Z!!J-U!#3"4jQ!!"m5'lrr%kk'GKBMb"Z!!JjD!!Bqe!b22rJ-$`!!G"Xqe$
X$`$!m`!#!36P!qdi[22q3"%+R2bcl6Nkk'@lHr!!++8$rqL!XrrSJ3$&Xqe!!E#!
XXrrSJEJ!))8!!(Mmm!!*1ZJ'k9)mr2!!36VS"X&52,blrr%kk'9TBMdjH6R919J!
X!)'i!##!S!"jR!!!8,bcrqNkk'5jBMb"Z!!K#U!!H-$`!!'!!!!*1ANje6PEri%K
XZrrK1ZKNS@)mJEJ!--#J!'Q!!!!+`I!"#C`!!"Q!!!#*#E[rJ5'lrmNKZrr4)E[r
XJ6VS8"Ylm!!aJ!!%5B!!!$V"m!%"R!!!'B!!!LL"Z!!`J+!!F,8$rr#"Zrr`jD!!
X1qe)J,2rk)%!aI!!#!'`[,[rm6VS6X&L25J"R!!"%5'lrmNKZrr3[,[rm6VS6V0l
Xm!!a)J$e!rr!`,[r`C`!!)L!Zrr5`V2rkCJ!!&LmXrrT1ZKKX@)mr,[rb6VS!VP5
X2)#crqL"!-@cl8!"XB!!!IQ!!!!k`I!"'C`!!"Q!!!"3[,2rk6VS6EPL2B!!!B'!
X!!!k`I!"(C`!!"Q!!!"3[,2rk6VS6GPL2B!!!3Q!!!!k`I!")C`!!"Q!!!"3[,2r
Xk6VS6IPL2B!!!*'!!!!k`I!"*C`!!"Q!!!"3[,2rk6VS6KPL2B!!!"Q!!!!)[,[r
Xi6VSAc&L26Pj1G8j@!!"1ANje6PB!!%jH6R919[rZ$'i!!3!)CJ!!#Nkk!ZTJ!!#
XZ5'lrmNKZrrT)E[rq2bi!##mXrrT1ZK'@h[`!%JaZ!!ArrQB!!#J[,[rk6VSAS&L
X228$rrM!m!!'3!'lrrMm!,blrqNkk&hCFMf!!!')`2!!-X'i!#'i!!#B-EJ!2!!K
XZ!!!F-#cl8X"m!3"R!!!-2bi!#%kk!$a8Mf!!!$)-EJ!4!!KQ!!!S6VS-5Le!rqi
X-J!#3"'B!!!CJ!!!53QF[,[rZ6VSA1Pb2B!!!!NjH6R919[r#6VS-(#e!rr`-VJ#
X3"2rmCJ!!"Q!!!IS`,J!)B!!!!V"m!!jR!!!'B!!!&L"Zrra"k!!N,8Mre'!!!"j
XJ!!!1X(`!$fF!!!CJ!!"+)'lrr%(S!#!Y52r8)'lre&+Zrp3G82rB)'lre&+Zrp3
XG82rC)'lre&+Zrp3G82rD)'lre&+Zrp3G82rE3Llrh'!!!6TJ!!!DX(`!$'F!!"*
XJ!!!#X(`!$@F!!!CJ!!%H)'lrr#eS!%crd%KZrm)[,[r36VS9DP#2-#lra%M!JI`
X!#Mm!6VS"3P52(8$rf$mZrm41ZJ%d9)mG32rC(A`!,rrD-#lraNM!JI`!#Mm!6VS
X"'&52(8$rfcmZrmC1ZJ%+9)mG32rF(A`!,rrG-#lr`NM!JI`$k$m!6VS!lP52(8$
XrhM!Zrm*)`)(m!'3r!%kk!0K8Mae!rpm`,[r#5-#"r!!+2`"1ZJ$#9)mG32rJ2bl
Xr`Nkk!,48Mae!rq%GI!!Jrq)`,[r)5-#"r!!+2`"1ZJ#B9)mG32rM2blrb%kk!)T
X8Mae!rq3GI!!krq8`,[r+5-#"r!!+2`"1ZJ"Z9)mG32rQ2blrbNkk!'"8Mae!rqG
X#,[rSB!!!"Q!!!!*)E[rX5'lrp%KZrqSr,J!),bcrqNkk$aVHr!!55'lrf#mZrr4
X1ZJp%8)p#Cd*R2bi!##mXrrT1ZJpBh[`!#LmXrrT1ZK#X@)p1ANje6PB!!$!Z!!K
X)`)(m!!T)30"m!$"J!!!#6Pj1G8j@rqa#E2SJ2A`!![rXB!!!PNKZrr")E[rm5'l
XrlMmZrq`[,2rk6VS1S0lm!")[,[rm6VS8Y&L25N"R!!"85'lrm%KZrrK)E[rZ-#l
Xrl&j!2`![,2rk6VS1F0lm!"*)E2RJ,blrq%kk$Rj3MdKXqH!`,[rX`I`!C%(Xq9V
X3`%(3,`K1ZJF+8)p5E2SJB!!!&$!Zrqc"r!"N3Hcj@Y$!-,crpP*Zrq`-EJ!%rqa
X[!2pN-$`!!$P!qK3j32S@5'lrm%KZrra)E[rZ2c`!##mXrrT1ZJhfh[`!%LmZrra
X1ZK3+@)mj32S@-#ck&QF!!$K)E[r`5'lrq%KZrqir2!!2,bcrqNkk$F6Hr!!55'c
Xji#mZrrK1ZJh58)p"l2RJ)!JJ3#P3qKa)E[r`5'lrr%KZrqir2!!(,bcrqNkk$Bl
XHr!!5,blrr%kk%k*BMcP!qK3`,2S8C`!!1%KZrr")E[ri5'lrlMmm!!i[,2rk6VS
X0A0lm!"*)E2RJ,blrq%kk$@T3Md(XqH!J##"!+9$k'%KZrr")E[rm5'lrlMmm!!8
X[,2rk6VS0*Ylm!")[,[rm6VS61PL218$k#$!XqJKR!!!k5'lrm%KZrrK)E[rZ2c`
X!$#mXrrT1ZJcdh[`!%NKXqH![,[ri6VS0!P#25'cji%kk#ECBMbP!qJa)E[r`5'l
Xrr%KZrqir2!!',bcrqNkk$,cHr!!5,blrr%kk%Y"BMcP!qJS`,2S+C`!!1NKZrr"
X)E[ri5'lrlMmm!!d[,2rk6VS-LYlm!"*)E2RJ,blrq%kk$*K3MdKXqH"1ZJP-@)m
XT32S35'lrm%KZrra)E[rZ2c`!%#mXrrT1ZJa5h[`!%LmZrra1ZK*Q@)mr!%kk!!K
X8MdjH6R919J!!-$`!!$P!q6Bj32RH3Hcj1#P)rfK#CdKXreC1ZJm@A)p#V2q@1@c
XrE2qJ3Qcj@$!Z!!KR!!!-)$`!N!-#B!!!"L!XriBT32PD-#i!#'B!!!C#,2Ni,cc
XrN!4#Tc!Xqdj53$m!6VS4PYlm!!ST32rf6VS!*#mXrrC1ZJf8@)m[,2rk6VS0I&L
X2,bcrpNkk%BKBMdjH6R919J!!6VS%4!aX!#$j@'d!!#B-E!!!q6CQ!!!B3UF`,2Y
X19%!r!%kk%34FMcPm!!(j0Q!!!E3`,2RHC`!!*JaX!!,jhQB!!!C#E2RH$'`!!2P
XBCJ!!#Q!!!GaJ!!!'B!!"L$!Xq9MPJ%(Xq,E3`##m!*!$!6!Xq9M"r!!J3Hcl90$
X!3G!T52qF-#cj@-(m!#""l2Y8d-"#%$!Xq9MPJ%(Xq,E3`#!318$rTM!Xq9MPJ%(
XXq9V3`#P3rlT#CdKXriT1ZJf)A)mj32p8$'`!!2p8CJ!",$!XqL"R!!"S-#cj@-(
Xm!#""l2Y8d-""d#m)5'ck)Nkk"'T3MdT!CJ!!4M!Xq9M"r!!J3Hcl90$!3G![#%K
XXqSC1ZJ4)8)p+3'B!!#3`,2PB`I`!)%(Xqe63`%(3,`K)E2VU6VS%*P#25N"R!!#
X#-#ck&QF!!"3J,2SF3HcrUL)))%'`N!"Q!!"S-#ck&'F!!"3J,2SB3HcrVL)))%'
X`N!"Q!!"1-#ck#'F!!"!J,2S-)LcreV#"BJ!!1$!XqJTR!!!3)#ck%#)XrpD`J@8
X!!#)`,2PBjB""l2PDd-![%"!XrkK)J$m!2bcj@%kk!(T3Ma!XrkK)J-"m!""R!!!
XL8Qcj@$!Xq9MPJ%(Xq9V3`##XrlTJ!2iH8fcj@%*Xre3`,2PBjB""l2Lfd-"5N!!
X-E!!!re4Q!!!+-#cjhQF!rQB-E!!#qGjQ!!!'3QcjhJaX!!$j@'B!!!TJ!!!+B!!
X!"Q!!rlC1ANje6PErqN(Xp!BY52rk)'lrqN)3%#cj1'F!!#T)E2Ni,blrqNkk!F4
X3Mbe!rrT)E!!!,blrqNkk!E*3Mbe!rrTJ!!!S-#i!#'B!!!i`,J!+`(`!%'F!!"4
X)E!!#,blrqNkk!BK3Mbe!rrT#E[rqB!!!8M!Zrrl"r!!J3Hcl90$!3G![##mZrrT
X1ZJ&J8)mY32rk-#lrrV"Z!!KQ!!!-3H`!"#!)B!!!#%(X!!BJ##m!,blrqNkk!64
X3Mbe!rrT5E[rq-#lrrV"Z!!K[!2qQ-#i!#-(m!#""l2Y8d-""d#m)-#i!#-(m!#"
X"l2Y8d-""d#m)6VS!pP#25'`!%M!Z!!V!I!!3C`!!$%(X!!JJ#'!!!!K"l!!-)!J
X[!%KXp!B`,J!)`I`!)%(Xqe63`%(3,`K1ZJI+h[`!%#mXrrC1ZJS5@)m[,2rf6VS
X*l&L2,bcrpNkk#G4BMbmXrrC1ZJhm@)pJ!!"m5'lrrN+R6VS)i&#2-#lrrQ!!!!+
X`I!!#C`!!"Q!!!!`jI!!"qGjJ!!!1X(`!!@F!!!CJ!!!1B!!!5Q!!!$jJ!!!1X(`
X!!fF!!!CJ!!!8)(`!!!1B)+i!$'!!!#"J!!!1X(`!"QF!!!CJ!!!31A`!![RHB!!
X!$Q!!!!)`2!!"CJ$rJ%jH6R919J!!51F!-#CZ!!JNEJ!-B!!!!KEDCJ$rr&1,)!Y
XJ!!!#60m-!%jH6R919J!!6VS-N!"+!'F!!!JjI!!"qGj1ANje6PB!!%MR!6!QEJ!
X)*'i!$'!!!0S3'Ki!5)"J!!!#X(`!+QF!!!CJ!!!10[crrf!!!,aJ!!!1X(`!2fF
X!!!CJ!!!10[crrQ!!!+4J!!!1X(`!*'F!!!CJ!!!N%"*)J,"m!!"Q!!!+-$crr@!
X!!!B3"dL!0X"J!!"fB!!!$V"m!!"R!!!'B!!!&"!(5)!f`'!!!'4J!!"BB!!!$V"
Xm!$TR!!!'B!!!4"!D5)!f`!a!!!"Q!!!'B!!!2Q!!!$*J!!!#-$`!34)(5)'`3@i
X!!")3"dL!X(`!@Qi!!!EH2!!J%!G)J$E!B!!!"Q!!rpB`2!!"CJ$r)NcI$)"1ANj
Xe6PErpNMR!$!QEJ!)*'i!$#e+rr`Y5rriB!!![Ja6rrpQ!!!8,8Vrr'!!!!48L`a
X6rrpR!2ri$&-!!'B!!!S`2!!"B!!!R"!D`(`!rae!rrG)J,"m!!"Q!!!D$&2rr@B
X!!!S`2!!"B!!!"M!m!!"J!!"`-$`!34)ZrrG)JE""EJ!!&K!ZrrG)J,"m!&TZ!!!
X)"Li!)2rh-"X5,[rh5)'`3@F!!!`-DrrqrrjQ!!!'B!!!+#!Zrra5J#4!B!!!&#!
X,X+lrq'B!!!S`2!!!B!!!%JaMrrpQ!2rS-$`!!@B!rcj-h``!6Pj1G8j@!!!r2!"
X'2c`!4NKXmlK1ZJZb8)p1ZJIL'A`!!I1m5'cc[#mm!*!%5'`!&$mmrrm[2!#3"#m
Xm!*!%5'ccZ%kk#I6Hr!!D%#cc['B!!!S`22rrB!!!)%KXmmB[,J!-6VS+Q&#2)'i
X!#$#Xmm)`2!!!B!!!!NjH6R919[rm5'cd"NKZrrj1Z[pf8)p+3'F!!!`J2!#3"'!
X!!%4#V20d3Hcd"LP)mhSjE[rqmhj#,21#3QG)E20S6VS*lPb228$rr$!ZrraR!!!
X-)$`!N!4J!!!-3HccD#!)B!!!!NjH6R919J!!51F!-#CZ!!JNEJ!-3T*J!!!S)")
X[!#!m!*!$#Lm!6VS'XL!I&K2'I!$r5-23Jj!![!#3!c!NJ&+,-$`!-")65)'`3@i
X!!!i3%dL!X(`!1@m!rm)J#f!!!!*-h``!6Pj1G8j@!!![,J!-,bi!#%kkrij3Mbe
X!!!JJEJ!)8Ui!#"!35)#`I!![C`!!$P1Z!!JJ,J!)B!!!ALmZ!"![,J!)6VVrA&#
X2,8!!##"Z!!K5VJ!)%"")J,"m!#pR!!!18ki!##!Z!!KJ!!!X,bi!&#mZ!!K1Z[m
XU8)mY3!!))'i!&!b3!!!!"faN!!!-)'i!&!D3!!!!"fa1ANje6PB!!#mZ!!`[,J!
X)6VVqq&#2,8!!##"Z!!K5VJ!)%"")J,"m!$TR!!!18ki!##!Z!!KJ!!!F,bi!%#m
XZ!!K1Z[l'8)mY3!!))#i!#'!!!!*1ANje6PErr%MR!$!QEJ!)%"0)J,"m!#eQ!!!
X58SXJ#bm!6VS!9PL2B!!!5#4,B!!!+"!55)#`I!![C`!!$K!55)#`I!!kCJ!!$Lm
X,6VS!lPL2B!!!(P++%"*Q!2r@5'lrr#m,6VVq8&#2)#lrr'!!!!*-h``!6Pj1G8j
X@rrJ[#bCZ!!K)E[ri,`Y1Z[iU8)mQ3"!65)"J!!!#X(`!C'F!!"*J!!!#X(`!4'F
X!!!CJ!!!5,A`!!9'!rraJ!!"DB!!!'V"m!'KR!!!5B!!!!V"m!%KR!!!'B!!!%Le
Xm!!!1%2rmB!!!-Q!!!"U`I!"YC`!!%Q!!!!+`I!"0C`!!"Q!!!")YI!#3!ccrr'!
X!!!TJ!!!'B!$rRL"m!!!#$#!3)Llrr#m")Llrq#m"6VS$p#)IN!#"B!!!!LCI6Pj
X1G8j@rpB[#bCZ!!JJ22lYUkdY32rX,8$rr#e!rr4#V[rDB!!!a'!!!,B`2!!`%K0
X)JE""EJ!!TK!65)#`I!!jEJ!!QLe,rpCJ!!!D)'lreK!35)#`I!!!CJ!!"Q!!!#C
X5V[r@)'lreK!35)#`I!![C`!!%L"ZrpB3%%L!X(`!1QB!rmSJE[r@%"")J,"m!!"
XR!!"#)'lreK!35)#`I!![CJ!!(NKZrr4)E[ri5'lrr#m,6VVp,0lm!"!Q3'!!!"C
X)E[rX5'lrm#m,6VVpUYlm!!`Q3'!!!!jJ!!!%8SX3%fB!rdK5V[rD$+i!N!-#rpT
XP!2md5'lrhL"m!!!#$#m36VS'(P#23Qlrk#!Zrrb`[2lYUkeR!!!d-$`!!$e!rqB
Xp32rN)#lrp,#mrZfVV@F!!!SJ,[rd28$rhL!Zrr`p32rJ)#lrq$e!rq)J,[rXX,c
XqlDZYC`!!%L!Zrq`p32rQ)#lrm$e!rq4)E[rD5'lrhNkk"CT3Mb!ZrpTJ!!!#*Pp
X1ANje6PB!!#mZ!!K1ZJ$D@)m[,J!-6VS!d&L2,bi!%%kk!-CBMbmZ!"41ZJ#m@)m
X[,J!),bi!$#mZ!"![,J!8UBX[,J!)6VS!f&L2,bi!$%kk!-jBMbmZ!""1ZJ$%@)m
X[,J!86VS!ZPL26Pj1G8j@!!![,J!)2bi!$#mZ!!i[,J!5,bi!&UQ06Pj1G8j@!!!
X[,J!),bi!$+Q3!#mZ!!a1ZJ#!@)p1ANje6PB!!#mZ!!a1ZJ!f@)m[,J!),bi!$+Q
X2,bi!$%kk!&TBMdjH6R919J!!,bi!#$mZ!!`r,J!12bi!%+Pq6Pj1G8j@rrT)j`-
X3*Qi!##e,rrSJ#fFF("0)KM!(&X!q"M!'C[)J#j!!V[rk8d!JE[rk%)"-h`M!6Pj
X1G8j@!!")j`%`*Qi!##!,Ca`Z#e+,*%FJ4ai3cR`!rf!#&0X`"e0(5N"QpN)560m
X-J%jH6R919J!!,bi!##mZ!!bTN8jH6R919J!!98m[,J!)UAm3(dL!6Pj1G8j@!!"
X96bmZ!!J[,J!-,bi!%+Q!%"p)J%jH6R919J!!)#i!##"!$'J!N!1NE4!J,J!))%!
X[+!#J6VS$C&L26Pj1G8j@!!!J,J!))%!-D!#3!k4Y%#!Z!!JJ3#mS!+"1ZJ0-@)p
X1ANje6PB!!#!Z!!JJ3!aS!*!$T'd3)#i!##"!,bJ!S%kk!c4BMdjH6R919J!!)#i
X!##"!$'J!N!1NE4!J,J!))%![+!#J6VS$(&L26Pj1G8j@!!![,J!)UB&1ANje6PB
X!!#mZ!!LT(djH6R919J!!,bi!#+N@6Pj1G8j@!!![,J!)U491ANje6PErqLm!3Ql
XrrNUZ!!KX#&*Zrrj%VJ!)5Ui!$'`)8QlrrN5Z!!``,J!+`1i!$Le!rrS`,J!)`1i
X!$Y&ZrrS`,J!+`1i!$0&ZrrS#EJ!"rrjR"%5ZrrSJ(beZrrS!$%jH,Tp+V`!%6R9
X1ANje6PErr#m!-#i!#X$Z!!iY32rm-#i!#-$Z!!l4E[rm-#i!#X$Z!!c4E[rm)"m
XYE[rm!!a1ALkI5Um!"%je6Pj1G8j@!!#S8djH6R919J!!)(`!!!2f$&$rrfB'-$`
X!$'!i)'i!##mS!"*1Z[fX@)mJEJ!)-$`!#8SZ!!eR"+CJB!+LB#"Z!!J[+!!56VV
Xp`PL2)'i!#$!S!""1ANje6PB!!#"Z!!K+,J!0C`5Q&'!#SK3JEJ!),bJ!%NkkrC4
XBMb"Z!!J`+!!36Pj1G8j@rrj+U3!8C`j)HZM86VS![&L26Pj1G8MRF$J[1!+f,`J
X[#6!T!"K%3&0!kd!!3-!!28$rrPQ2,ca%394"2`#TS%+%5TFQAfF)@Bm[#kQP+"m
Xk220S5-9%K5!&d)5M)U!T)PFM5!!8+&$Ca5(-!VC+K'F-)&-L6#!%S#i[#kQM@Bm
X[2%P1593r,[rqUD"+PbCIC`JJ8dk3!#m,UD-'E!!"rrj1ZZJm)Pm[!#"T!"3%E!!
X"rrjQ!U!U)"mJAc&!!"!Kh`+f60mF$NjH6R919J!!51G`1#mi!VB[##m*)'N!&+!
XT+&!k220S4%ABa5(-!VB'E!!"rriJEJ!)6T!!)Pm[!#"T!"3%E!!"rrjQ!U!U)"m
XJAc&!!"!Kh`+f60mF$NjH6R919J!!5(VTf%kkrk"BMdjH6R919J!!5(VSCNkkrij
XBMdjH6R919J!!5(VT[%kkrhaBMdjH6R919J!!,`P)HZJ56VVrD&L2)Pm[!#"T!"5
XJ)d+T!"3J(djH6R919J!!,bi!#+R@6Pj1G8j@!!![,J!)UG91ANje6PB!!#mZ!!L
XTfdjH6R919J!!,bi!#+RA6Pj1G8j@!!!JEJ!),a![,J!-,bi!%$mZ!"3[,J!@,bi
X!'LmZ!"ir2!!#UHSJEJ!H3HJ!#Lm)6VVlR&L26Pj1G8j@!!!JEJ!)UFFLEJ!-)S"
X1ANje6PB!!#!Z!!JJEJ!-UFC1ANje6PB!!&92UA33(dL!6Pj1G8j@!!!JEJ!),bJ
X!%NkkqaKBMb"Z!!K+,J!0C`5N$'!#S!`JEJ!),bJ!%Nkkqc*BMb"Z!!J`+!!36Pj
X1G8j@!!"96cmZ!!J[,J!+UBF`(djH6R919[rm51F!-#CZ!!JNEJ!-,8[rr"EDC[`
XJ,[rm60m-!%jH6R919J!!@8mr,J!),bi!#LmZ!!kTI#!I6Pj1G8j@!!![,J!)UB0
X1ANje6PB!!#mZ!!LSFdjH6R919J!!,bi!#+Kd6Pj1G8j@!!![,J!)2bi!$+PM6Pj
X1G8j@!!"96bmZ!!LTB$!I6Pj1G8j@!!!JEJ!),bJ!%NkkqMTBMb"Z!!K+,J!0C`5
XN&@!#S"8JEJ!),bJ!%NkkqP4BMb"Z!!J`+!!36Pj1G8j@!!![,J!)2bi!$$mZ!!k
XSJ%jH6R8!!!%!N!-Hm3!!(I%!N!1a!!'&*J&k!*!$(!#Q!!4"6&*8!*!$+N4*9%`
X!!J!f4%a24`!"!&T%394"!*!$FN459P)!N!0q`B,rr`#3#-'!rrm!N!-3!*!%`B(
Xrr`!!!CJ!N!6"J[rr!!!#D!#3"-'!rrm!!!,i!*!%`B(rr`!!!ai!N!6"J2rr!!!
X$33!"K0i!$!#3"!0E!!'*+JS!5%C6)%CTEQ3JAJS:
---EOF-EOT-M-O-U-S-E---
set FOO `$CSUM hfsfda.hqx`
if [ X$2 != X13374 ]
then
    echo bad checksum: hfsfda.hqx
fi
exit
# -------------------- cut here -----------------------------
-- 
member, all HASA divisions              POELOD  ECBOMB
					--------------
					       ^-- Secret Satanic Message

Tim Smith       USENET: sdcrdcf!ism780c!tim   Compuserve: 72257,3706
		Delphi or GEnie: mnementh