[net.sources.mac] Source for Grep-Wc DA

dubois@uwmacc.UUCP (Paul DuBois) (03/17/86)

This posting contains several files:

uGrep.src	 "Uses" file with all constants and types needed to
		 compile Grep-Wc
GrepPatStuff.src Pattern-compiling, matching and entry routines
Grep-Wc.src	 Main program
Grep-Wc.rsrc.Hqx BinHex of Grep-Wc resources
AddRes.src	 Utility for transferring resources (not necessary,
		 but very helpful)

You will also need the stream library stuff (__StreamLib.src - separate
posting).

The pattern compilation and matching routines are based in algorithms
found in the Software Tools (Kernighan and Plauger).  The resource
copying stuff in AddRes is similar to some parts of the Rascal program
MakeAppl.  uGrep.src is a conglomeration of parts of Rascal "Uses" files,
but since there is very little there that isn't listed explicitly in
Inside Macintosh, I don't expect that I am violating any rules by posting
it.


To recreate Grep-Wc from the source code, do the following
steps:

Launch Rascal
Compile __StreamLib.src to get __StreamLib.ras
Compile uGrep.src to get uGrep.ras
Compile GrepPatStuff.src to get GrepPatStuff.ras
Compile Grep-Wc.src to get Grep-Wc.ras
Link Grep-Wc.ras to get Grep-Wc.obj.  DON'T execute it!!  (It needs
its own resources to run properly.)
Express AddRes.src to get AddRes.obj.  This program is a simple utility
which asks you to select two files, then copies all the resources from
the first one into the resource fork of the second one.  When you
run this, select Grep-Wc.rsrc as the first file ("Copy From") and
Grep-Wc.obj as the second file ("Copy To").  (You could use ResEdit
to accomplish the same task.)
Execute Grep-Wc.obj in Rascal to see if it works.  Assuming it does,
go on to the next step.
Execute DeskMaker.obj (you must have the version from the new Rascal
release).  Stretch/move the window to where you want it, select the
Object -> Desk Acc. menu item.  When the dialog comes up, change
the window type to 0 (zero).  Do NOT select "Test after make" (the
DA file that DeskMaker won't have the necessary owned resources).
Note the driver number that DeskMaker assigns to the new DA.  If
it's 26, then quit DeskMaker and use AddRes to copy Grep-Wc.rsrc into
the new DA file.  You're all set.
If the id was not 26, then use ResEdit to copy the resources from
Grep-Wc.rsrc into the new DA file, and change their owner id's to match
the driver number (don't change the sub-id's).  There are ALRT, DITL
and DLOG resources.  If you don't renumber them properly, Font/DA Mover
won't move them when you move the DA around.  See the discussion on
owned resources in the Resource Manager manual of Inside Macintosh
if you don't know what I'm talking about here.


#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	uGrep.src
#	GrepPatStuff.src
#	Grep-Wc.src
#	Grep-Wc.rsrc.Hqx
#	AddRes.src
# This archive created: Mon Mar 17 10:50:22 1986
# By:	Paul DuBois (UW-Madison Primate Center)
echo shar: extracting uGrep.src '(8926 characters)'
sed 's/^XX//' << \SHAR_EOF > uGrep.src
XX
XXProgram uGrep;
XX
XX(*
XX    uGrep.  Uses file containing all Toolbox Types and Constants needed
XX             for Grep-Wc (gleaned from various u* files).  Many of the
XX             handles and pointers I simply declared as ^LongInt, however.
XX
XX*)
XX
XX(*$U+*)
XX(*$L+*)
XX
XX
XXCONST
XX
XX(*  from uMemTypes  *)
XX
XX   True = 1B;
XX   False = 0B;
XX   Nil = 0L;
XX
XX(*  from uQuickDraw  *)
XX
XX(*  from uToolIntf  *)
XX
XX    inGrow = 5;
XX
XX  (*control definition proc ID's*)
XX
XX  pushButProc   = 0;
XX
XX(*  from uOSIntf  *)
XX
XX  NoErr       =      0;     (* All is well *)
XX
XX  fsWrPerm  = 2;
XX  
XX(*  from uPackIntf *)
XX
XXTYPE
XX
XX(*  from uMemTypes  *)
XX
XX   Boolean = Byte;
XX   char = Integer;
XX   SignedByte   = Byte;         (* any byte in memory *)
XX   Ptr         = PtrB;         (* blind pointer *)
XX   Handle       = ^PtrB;        (* pointer to a master pointer *)
XX   ProcPtr      = Ptr;         (* pointer to a procedure *)
XX   Fixed        = LongInt;      (* fixed point arithmetic type *)
XX
XX   Str255       =  Byte[256];   (* maximum string size *)
XX   StringPtr    = ^Str255;      (* pointer to maximum string *)
XX   StringHandle = ^StringPtr;   (* handle to maximum string *)
XX
XX(*  from uQuickDraw  *)
XX
XX     Style     =  Integer;  (* use this one. *)
XX     Pattern   =  Byte[8];
XX
XX   Point = Record
XX     Variant
XX         { v,h: integer ;};
XX     or  { vh:  longint ; };
XX   End;
XX
XX     Rect = Record 
XX       Variant
XX          { top,left,bottom,right:  Integer ;};
XX       Or
XX          { topLeft,botRight: Point ; };
XX     End;
XX
XX
XX     BitMap = Record
XX       baseAddr: Ptr;
XX       rowBytes: Integer;
XX       bounds:  Rect;
XX     End;
XX
XX
XX
XX     RgnHandle = ^LongInt;
XX     QDProcsPtr = ^LongInt;
XX
XX
XX     GrafPtr  = ^GrafPort;
XX     GrafPort = Record
XX       device:     Integer;
XX       portBits:    BitMap;
XX       portRect:    Rect;
XX       visRgn:     RgnHandle;
XX       clipRgn:     RgnHandle;
XX       bkPat:     Pattern;
XX       fillPat:     Pattern;
XX       pnLoc:     Point;
XX       pnSize:     Point;
XX       pnMode:     Integer;
XX       pnPat:     Pattern;
XX       pnVis:     Integer;
XX       txFont:     Integer;
XX       txFace:     Style;
XX       txMode:     Integer;
XX       txSize:     Integer;
XX       spExtra:     Fixed;
XX       fgColor:     LongInt;
XX       bkColor:     LongInt;
XX       colrBit:     Integer;
XX       patStretch:  Integer;
XX       picSave:     Handle;
XX       rgnSave:     Handle;
XX       polySave:    Handle;
XX       grafProcs:   QDProcsPtr;
XX     End;
XX
XX(*  from uToolIntf  *)
XX
XX
XX  (*for TextEdit*)
XX
XX  TERec = Record
XX    destRect: Rect;      (*Destination rectangle*)
XX    viewRect: Rect;      (*view rectangle*)
XX    selRect: Rect;      (*Select rectangle*)
XX    lineHeight: Integer;     (*Current font lineheight*)
XX    fontAscent: Integer;     (*Current font ascent*)
XX    selPoint: Point;      (*Selection point(mouseLoc)*)
XX
XX    selStart: Integer;      (*Selection start*)
XX    selEnd: Integer;      (*Selection end*)
XX
XX    active: Integer;      (*<>0 if active*)
XX
XX    wordBreak:  ProcPtr;     (*Word break routine*)
XX    clikLoop:  ProcPtr;      (*Click loop routine*)
XX
XX    clickTime: LONGINT;      (*Time of first click*)
XX    clickLoc: Integer;      (*Char. location of click*)
XX
XX    caretTime: LONGINT;      (*Time for next caret blink*)
XX    caretState: Integer;     (*On/active booleans*)
XX
XX    just: Integer;      (*fill style*)
XX
XX    TELength: Integer;      (*Length of text below*)
XX    hText: Handle;      (*Handle to actual text*)
XX
XX    recalBack: Integer;      (*<>0 if recal in background*)
XX    recalLines: Integer;     (*Line being recal'ed*)
XX    clikStuff: Integer;      (*click stuff (internal)*)
XX
XX    crOnly: Integer;      (*Set to -1 if CR line breaks only*)
XX
XX    txFont: Integer;      (*Text Font*)
XX    txFace: Style;      (*Text Face*)
XX    txMode: Integer;      (*Text Mode*)
XX    txSize: Integer;      (*Text Size*)
XX
XX    inPort: GrafPtr;      (*Grafport*)
XX
XX    highHook: ProcPtr;      (*Highlighting hook*)
XX    caretHook: ProcPtr;      (*Highlighting hook*)
XX
XX    nLines: Integer;      (*Number of lines*)
XX    lineStarts: Integer[16000];     (*Actual line starts themselves*)
XX  END; (*Record*)
XX
XX  TEPtr = ^TERec;
XX  TEHandle = ^TEPtr;
XX
XX
XX  (*for Resource Manager*)
XX
XX  ResType = Longint; (* Packed Array of 4 Chars *)
XX
XX
XX  (*for Control Manager*)
XX
XX
XX  ControlHandle    = ^LongInt;
XX
XX  (*for Dialog Manager*)
XX
XX  DialogPtr=    ^LongInt;
XX
XX
XX  (*for Menu Manager*)
XX
XX  MenuHandle = ^LongInt;
XX
XX
XX(*  from uOSIntf  *)
XX
XX  (*for Event Manager*)
XX  EventRecord = Record
XX    what:      Integer;
XX    message:   LongInt;
XX    when:      LongInt;
XX    where:     Point;
XX    modifiers: Integer;
XX  End;
XX
XX  OSErr = Integer;
XX  
XX
XX  QElemPtr = ^LongInt;
XX  
XX
XXIOParam = Record
XX   ioRefNum: Integer;       (*refNum for I/O operation*)
XX   ioVersNum: SignedByte;   (*version number*)
XX   ioPermssn: SignedByte;   (*Open: permissions (byte)*)
XX
XX   ioMisc: Ptr;      (*Rename: new name*)
XX                            (*GetEOF,SetEOF: logical End of file*)
XX                            (*Open: optional ptr to buffer*)
XX                            (*SetFileType: new type*)
XX   ioBuffer: Ptr;           (*data buffer Ptr*)
XX   ioReqCount: LongInt;     (*requested byte count*)
XX   ioActCount: LongInt;     (*actual byte count completed*)
XX   ioPosMode: Integer;      (*initial file positioning*)
XX   ioPosOffset: LongInt ;   (*file position offset*)
XXEnd;
XX
XX  OSType = Longint; (* Packed array of 4 chars *)
XX  
XX  FInfo = Record      (*Record of finder info*)
XX            fdType: OSType;         (*the type of the file*)
XX            fdCreator: OSType;      (*file's creator*)
XX            fdFlags: Byte;       (*flags ex. hasbundle,invisible,locked, etc.*)
XX            filler: Byte;
XX            fdLocation: Point;      (*file's location in folder*)
XX            fdFldr: Integer;        (*folder containing file*)
XX          End; (*FInfo*)
XX
XXFileParam = Record
XX   ioFRefNum: Integer;      (*reference number*)
XX   ioFVersNum: SignedByte;  (*version number*)
XX   filler1: SignedByte;
XX   ioFDirIndex: Integer;    (*GetFileInfo directory index*)
XX   ioFlAttrib: SignedByte;  (*GetFileInfo: in-use bit=7, lock bit=0*)
XX   ioFlVersNum: SignedByte; (*file version number*)
XX   ioFlFndrInfo: FInfo;     (*user info*)
XX   ioFlNum: LongInt;        (*GetFileInfo: file number*)
XX   ioFlStBlk: Integer;      (*start file block (0 if none)*)
XX   ioFlLgLen: LongInt;      (*logical length (EOF)*)
XX   ioFlPyLen: LongInt;      (*physical lenght*)
XX   ioFlRStBlk: Integer;     (*start block rsrc fork*)
XX   ioFlRLgLen: LongInt;     (*file logical length rsrc fork*)
XX   ioFlRPyLen: LongInt;     (*file physical length rsrc fork*)
XX   ioFlCrDat: LongInt;      (*file creation date & time (32 bits in secs)*)
XX   ioFlMdDat: LongInt ;     (*last modified date and time*)
XXEnd;
XX
XXVolumeParam = Record
XX   filler2: LongInt;
XX   ioVolIndex: Integer;     (*volume index number*)
XX   ioVCrDate: LongInt;      (*creation date and time*)
XX   ioVLsBkUp: LongInt;      (*last backup date and time*)
XX   ioVAtrb: Integer;        (*volume attrib*)
XX   ioVNmFls: Integer;       (*number of files in directory*)
XX   ioVDirSt: Integer;       (*start block of file directory*)
XX   ioVBlLn: Integer;        (*GetVolInfo: length of dir in blocks*)
XX   ioVNmAlBlks: Integer;    (*GetVolInfo: num blks (of alloc size)*)
XX   ioVAlBlkSiz: LongInt;    (*GetVolInfo: alloc blk byte size*)
XX   ioVClpSiz: LongInt;      (*GetVolInfo: bytes to allocate at a time*)
XX   ioAlBlSt: Integer;       (*starting disk(512-byte) block in block map*)
XX   ioVNxtFNum: LongInt;     (*GetVolInfo: next free file number*)
XX   ioVFrBlk: Integer ;      (*GetVolInfo: # free alloc blks for this vol*)
XXEnd;
XX
XX
XXCntrlParam = Record
XX  ioCRefNum: Integer;       (*refNum for I/O operation*)
XX  CSCode: Integer;          (*word for control status code*)
XX  CSParam: Integer[10];     (*operation-defined parameters*)
XXEnd;
XX
XX  ParamBlockRec = Record
XX  
XX        (*12 byte header used by the file and IO system*)
XX        qLink: QElemPtr;     (*queue link in header*)
XX        qType: Integer;      (*type byte for safety check*)
XX        ioTrap: Integer;     (*FS: the Trap*)
XX        ioCmdAddr: Ptr;      (*FS: address to dispatch to*)
XX
XX        (*common header to all variants*)
XX        ioCompletion: ProcPtr;  (*completion routine addr (0 for synch calls)*)
XX        ioResult: OSErr;        (*result code*)
XX        ioNamePtr: StringPtr;   (*ptr to Vol:FileName string*)
XX        ioVRefNum: Integer;     (*volume refnum (DrvNum for Eject and MountVol)*)
XX
XX        (*different components for the different type of parameter blocks*)
XX
XX        Variant
XX          Insert ioParam;
XX          Insert FileParam;
XX          Insert VolumeParam;
XX          Insert CntrlParam;
XX
XX      End; (*ParamBlockRec*)
XX
XX(*  from uPackIntf *)
XX
XX   SFReply = Record
XX     good: BOOLEAN;  (*ignore command if FALSE*)
XX     copy: BOOLEAN;  (*not used*)
XX     fType: OsType;  (*file type or not used*)
XX     vRefNum: Integer;  (*volume reference number*)
XX     version: Integer;  (*file's version number*)
XX     fName: Byte[64];  (*file name*)
XX   END; (*SFReply*)
XX
XX
XXprocedure z_z_z();{};
SHAR_EOF
if test 8926 -ne "`wc -c uGrep.src`"
then
echo shar: error transmitting uGrep.src '(should have been 8926 characters)'
fi
echo shar: extracting GrepPatStuff.src '(13365 characters)'
sed 's/^XX//' << \SHAR_EOF > GrepPatStuff.src
XXProgram GrepPatStuff;
XX
XX(*
XX    GrepPatStuff - routines for compiling patterns into internal form,
XX    for matching strings against the compiled pattern, and for presenting
XX    the pattern entry dialog.
XX*)
XX
XX
XXUses
XX    __ToolTraps
XX    (*$U+*)
XX    uGrep
XX    ;
XX
XXConst
XX
XX    bufSiz = 512;
XX
XX(*  pattern dialog items  *)
XX
XX    okButton = 1;
XX    cancelButton = 2;
XX    (* prompt statText = 3 *)
XX    patText = 4;
XX    linesRadioButton = 5;
XX    noLinesRadioButton = 6;
XX    numbersCheckBox = 7;
XX
XX(*  pattern special internal chars  *)
XX
XX    CCL = 1;           (* match characters in class *)
XX    NCCL = 2;          (* all but characters in class *)
XX    CRANGE = 3;        (* range of chars *)
XX    ENDCCL = 4;        (* end char class *)
XX    ANY = 5;           (* match any char *)
XX    CLOSURE = 6;       (* closure *)
XX    EOL = 7;           (* end of line *)
XX
XX
XXVar
XX    theDialog:  DialogPtr;
XX
XX(*  pattern compilation and matching vars  *)
XX
XX    rawPattern: Byte[bufSiz];   (* pattern user types in *)
XX    thePattern: Byte[bufSiz];   (* compiled pattern *)
XX
XX    matchBol: boolean;          (* match beginning of line? *)
XX    pix: integer;               (* index into pattern *)
XX    pMark: integer;
XX    canClose: boolean;
XX
XXExtDef  (* externals from main program *)
XX
XX    resBase:    Integer;    (* base resource id *)
XX    matchType:  Boolean;    (* true: print lines w/pattern. false: inverse *)
XX    prtLineNum: Boolean;    (* print line numbers if true *)
XX    havePat:    Boolean;    (* whether have good pattern or not *)
XX    lineNum:    LongInt;
XX
XX(*
XX    PToCStr - convert Pascal string to C string, in place
XX    CToPStr - convert C string to Pascal string, in place
XX
XX    These are here because this program was originally written in C
XX    and it was easier simply to convert the strings to work with the
XX    same algorithm, than to convert the algorithm to work with Pascal
XX    strings.
XX*)
XX
XXProc PToCStr (s: ptrb);
XXvar
XX    i, len: integer;
XX{
XX    len := s[0];
XX    loop (len > 0, i := 0, ++i, i >= len)   (* move contents down one *)
XX        s[i] := s[i+1];
XX    s[len] := 0;        (* add terminating null byte *)
XX};
XX
XXProc CToPStr (s: ptrb);
XXvar
XX    i, len: integer;
XX{
XX    loop (, len := 0, ++len, )    (* determine length of string *)
XX        if s[len] = 0 then break;
XX    loop (len > 0, i := len, --i, i < 1)    (* move contents up one *)
XX        s[i] := s[i-1];
XX    s[0] := len;        (* set length byte *)
XX};
XX
XX
XX
XX(* ----------------------------------------------------------------------- *)
XX(*                        pattern-compilation routines                     *)
XX(* ----------------------------------------------------------------------- *)
XX
XX(*
XX    ADD - add char to pattern (may be a metachar, not necessarily
XX        a literal character to match)
XX*)
XX
XXProc add (c: byte);
XX{
XX    thePattern[pix] := c;
XX    ++pix;
XX    thePattern[pix] := 0;
XX
XX};    (* add *)
XX
XX(*
XX    Put a closure indicator into the pattern, in front of the
XX    stuff that's to be closed.
XX*)
XX
XXProc addclose ();
XXvar
XX    i: integer;
XX{
XX    ++pix;
XX    loop (, i := pix, (*--i*), --i <= pMark)
XX        thePattern [i] := thePattern [i-1];
XX    thePattern [pMark] := CLOSURE;
XX    canClose := false;
XX
XX};    (* addclose *)
XX
XX(*
XX    have found something that may be followed by a closure.  set
XX    canClose to indicate that fact, and set a mark to remember where
XX    the closable thing is.
XX*)
XX
XXProc markit ();
XX{
XX    pMark := pix;        (* set mark in case closure comes up next *)
XX    canClose := true;
XX};
XX
XX(*
XX    compile character class.  pass pointer to char after '[' that begins
XX    the class pattern.  Return nil if error, else pointer to char
XX    after closing ']' bracket.
XX*)
XX
XXFunc Class (p: ptrb): ptrb;
XXvar
XX    c, type, low, high: byte;
XX{
XX    Class := nil;
XX    type := CCL;            (* 'character class' metachar *)
XX    if p^ = '^' then
XX    {
XX        type := NCCL;       (* 'match all but this class' metachar *)
XX        ++p;
XX    };
XX    add (type);
XX    loop (,,,)
XX    {
XX        c := p^;
XX        ++p;
XX        if c = ']' then break;          (* end of class pattern *)
XX        if c = 0 then return;           (* missing ']' - pattern error *)
XX        if p^ <> '-' then
XX            add (c)
XX        else        (* range *)
XX        {
XX            low := c;                   (* low end *)
XX            ++p;
XX            high := p^;                 (* high end *)
XX            ++p;
XX            if high = 0 then return;    (* pattern error *)
XX            add (byte (CRANGE));
XX            add (low);
XX            add (high);
XX        };
XX    };
XX    add (byte (ENDCCL));
XX    Class := p;    (* all ok *)
XX
XX};    (* class *)
XX
XX(*
XX    COMPILE - compile string into internal form suitable for efficient
XX        pattern matching.  String should be in C format.
XX*)
XX
XXFunc Compile (p: ptrb): boolean;
XXvar
XX    c: byte;
XX{
XX    Compile := false;
XX    pix := 0;
XX    thePattern[0] := 0;
XX    canClose := false;
XX    matchBol := false;
XX(*
XX    check for ^ - it's only special at beginning of line
XX*)
XX    if p^ = '^' then
XX    {
XX        matchBol := true;
XX        ++p;
XX    };
XX    loop (,,,)
XX    {
XX        c := p^;
XX        ++p;
XX
XX        if c = '*' then
XX        {
XX(*
XX    if canClose is true, there was a preceding pattern which can be
XX    closed (not closure, ^ or $), so close it.  otherwise, take *
XX    literally.
XX*)
XX            if canClose then    (* something to close *)
XX            {
XX                addclose ();
XX                continue;
XX            };
XX        };
XX
XX        if (c = '$') and (p^ = 0) then
XX(*
XX    $ only special at end of line
XX*)
XX        {
XX            add (byte (EOL));
XX            continue;
XX        };
XX(*
XX    at this point we know we have a character that can be followed by a
XX    closure, so mark the pattern position.
XX*)                
XX        markit ();
XX        if c = '\\' then
XX        {
XX(*
XX    use escaped chars literally, except null, which is an error
XX*)
XX            if p^ = 0 then return;      (* pattern error *)
XX            add (p^);
XX            ++p;
XX            continue;
XX        };
XX        if c = 0 then break;            (* done compiling *)
XX        case integer(c) of
XX            '.': add (byte (ANY));      (* match any char *)
XX            '[':                        (* match character class *)
XX            {
XX                p := class (p);
XX                if p = nil then return; (* class pattern error *)
XX            };
XX            otherwise add (c);          (* match char literally *)
XX        end;
XX
XX    };  (* loop *)
XX
XX    Compile := true;    (* all ok *)
XX
XX};    (* compile *)
XX
XX(* ----------------------------------------------------------------------- *)
XX(*                         pattern-matching routines                       *)
XX(* ----------------------------------------------------------------------- *)
XX
XX(*
XX    NEXTPOS - find position in pattern of next component to match
XX*)
XX
XXFunc NextPos (p: ptrb): ptrb;
XXvar
XX    c: byte;
XX{
XX    c := p^;
XX    ++p;
XX    if (c = CCL) or (c = NCCL) then
XX    {
XX        loop (,,, c = ENDCCL)        (* look for end of class stuff *)
XX        {
XX            c := p^;
XX            ++p;
XX        };
XX    };
XX    NextPos := p;
XX
XX};    (* nextpos *)
XX
XXFunc InClass (c: byte; p: ptrb): Boolean;
XXvar
XX    high, low, pc: byte;
XX{
XX    InClass := false;
XX    loop (,,,)
XX    {
XX        pc := p^;
XX        ++p;
XX        if pc = ENDCCL then return;
XX        if pc = CRANGE then     (* range *)
XX        {
XX            low := p^;
XX            ++p;
XX            high := p^;
XX            ++p;
XX            if (low <= c) and (c <= high) then
XX                break;          (* it's within the range *)
XX        }
XX        else if c = pc then
XX            break;              (* it matched this char of class *)
XX    };
XX    InClass := true;
XX
XX};    (* inclass *)
XX
XX(*
XX    OMATCH - match character c against the current pattern position.
XX*)
XX
XXFunc omatch (c: byte; p: ptrb): boolean;
XXvar
XX    pc: byte;
XX{
XX    pc := p^;
XX    ++p;
XX    case integer(pc) of
XX        CCL: return (inclass (c, p));
XX        NCCL: return (!inclass (c, p));
XX        ANY: return (boolean (c <> 0)); (* don't match end of line *)
XX        otherwise return (boolean (c = pc));
XX    end;
XX
XX};    (* omatch *)
XX
XX(*
XX    try to match pattern p at the given position in string s
XX*)
XX
XXFunc amatch (s, p: ptrb): boolean;
XXvar
XX    c: byte;
XX    cursp: ptrb;
XX{
XX    if p^ = 0 then return (true);    (* end of pattern, have matched it *)
XX    if p^ = EOL then
XX        return (boolean (s^ = 0));    (* must be end of string to match EOL *)
XX
XX    if p^ = CLOSURE then
XX    {
XX(*
XX    advance as far as possible, matching the current pattern position.
XX    when omatch fails, s will point 1 past the character that failed.
XX    back up one and try to match rest of pattern.  if that fails, keep
XX    retreating until back at point of original closure start.
XX*)
XX        ++p;        (* skip closure marker *)
XX        cursp := s;    (* save current string position *)
XX        loop (,, c := s^; ++s, omatch (c, p) = false)
XX            ;
XX        loop (,,, s <= cursp)    (* keep backing up *)
XX        {
XX            --s;
XX            if amatch (s, nextpos (p)) then return (true);
XX        };
XX        return (false);
XX    };
XX    c := s^;
XX    ++s;
XX    if omatch (c, p) then
XX        return (amatch (s, nextpos (p)));
XX    amatch := false;
XX
XX};    (* amatch *)
XX
XX(*
XX    MATCH - match string s against the compiled pattern
XX
XX    if matchBol is true, then anchor the match to the beginning of the
XX    string, else try the pattern against successive string positions until
XX    the match succeeds or the end of the string is reached.
XX
XX    s should be in C format.
XX*)
XX
XXFunc match (s: PtrB): boolean;
XX{
XX    if matchBol then    (* anchored match *)
XX    {
XX        return (amatch (s, thePattern));
XX    };
XX    loop (,,,)          (* floating match *)
XX    {
XX        if amatch (s, thePattern) then return (true);
XX        if s^ = 0 then return (false);  (* end of string but no match *)
XX        ++s;
XX    };
XX
XX};    (* match *)
XX
XX
XX(* ----------------------------------------------------------------------- *)
XX(*                 Display dialog box to get the pattern                   *)
XX(* ----------------------------------------------------------------------- *)
XX
XX(*
XX    item    type
XX    1       ok button
XX    2       cancel button
XX    3       prompt
XX    4       edittext item for typing in pattern
XX    5       "lines containing pattern" radio button
XX    6       "lines not containing pattern" radio button
XX    7       "print line numbers" check box
XX
XX    Puts the string entered into theString, which on return is
XX    empty if either the user clicked cancel or typed no string
XX    and clicked ok.
XX*)
XX
XXProcedure SetValue (itemNo: Integer; itemValue: Boolean);
XXvar
XX    itemHandle: Handle;
XX    itemType: Integer;
XX    rect: Rect;
XX{
XX    GetDItem (theDialog, itemNo, @itemType, @itemHandle, rect);
XX(*
XX    Note type conversion here.  True turns the control on.
XX*)
XX    SetCtlValue (itemHandle, Integer (itemValue));
XX};
XX
XXFunction GetValue (itemNo: integer): Boolean;
XXvar
XX    itemHandle: Handle;
XX    itemType: integer;
XX    rect: Rect;
XX{
XX    GetDItem (theDialog, itemNo, @itemType, @itemHandle, rect);
XX(*
XX    Note implicit type conversion here.  Any non-zero is true.
XX*)
XX    GetValue := GetCtlValue (itemhandle);
XX};
XX
XX(*
XX    Set the type of line to select.  Pass the value for the "Match lines
XX    containing pattern" button.
XX*)
XX
XXProc SetMatchType (withval: Boolean);
XX{
XX    SetValue (linesRadioButton, withval);
XX    SetValue (noLinesRadioButton, !withval);
XX};
XX
XX
XXFunc GetPatDlog (): Boolean;
XXVar
XX    itemNo, itemType: Integer;
XX    itemHandle: Handle;
XX    rect: Rect;
XX{
XX    GetPatDlog := false;
XX    theDialog := GetNewDialog (resBase, nil, -1L);
XX    SetMatchType (matchType);
XX    SetValue (numbersCheckBox, prtLineNum);
XX    GetDItem (theDialog, patText, @itemType, @itemHandle, rect);
XX    SetIText (itemHandle, rawPattern);
XX    SelIText (theDialog, patText, 0, 32760);
XX    ShowWindow (theDialog);
XX    loop (,,,)
XX    {
XX        ModalDialog (nil, @itemNo);
XX        case itemNo of
XX            okButton:
XX            {
XX                GetDItem (theDialog, patText, @itemType, @itemHandle, rect);
XX                GetIText (itemHandle, rawPattern);
XX                matchType := GetValue (linesRadioButton);
XX                prtLineNum := GetValue (numbersCheckBox);
XX                GetPatDlog := true;
XX                break;
XX            };
XX            cancelButton: break;
XX            linesRadioButton: SetMatchType (true);
XX            noLinesRadioButton: SetMatchType (false);
XX            numbersCheckBox:
XX                SetValue (numbersCheckBox, !GetValue (numbersCheckBox));
XX        end;
XX    };
XX    DisposDialog (theDialog);
XX
XX};    (* GetPatDlog *)
XX
XX
XXProc GetGrepPat ();
XX{
XX    if GetPatDlog () then
XX    {
XX        PToCStr (rawPattern);
XX        havePat := Compile (rawPattern);
XX        CtoPStr (rawPattern);
XX        if !havePat then
XX            Alarm ("Bad Pattern");
XX    };
XX};
XX
XX
XX(* ----------------------------------------------------------------------- *)
XX(*                         Pattern Initialization                          *)
XX(* ----------------------------------------------------------------------- *)
XX
XX(*
XX    Set pattern initially to empty pattern.  This is legal - it matches
XX    every line.  If a file is grepped without specifying a pattern, therefore,
XX    the whole file will be displayed.  A side effect of this is to turn
XX    grep on WORD files into a WORD-to-TEXT file converter, when the save
XX    output option is turned on.
XX*)
XX
XXProc InitPat ();
XX{
XX    rawPattern[0] := 0;
XX    havePat := Compile (rawPattern);
XX};
SHAR_EOF
if test 13365 -ne "`wc -c GrepPatStuff.src`"
then
echo shar: error transmitting GrepPatStuff.src '(should have been 13365 characters)'
fi
echo shar: extracting Grep-Wc.src '(14893 characters)'
sed 's/^XX//' << \SHAR_EOF > Grep-Wc.src
XXProgram Grep_Wc;
XX
XX(*
XX    Grep - Globally search for Regular Expressions and Print, i.e.,
XX        g/r.e./p
XX
XX    Wc - char, word, line/paragraph count
XX
XX    Special characters for patterns
XX
XX    ^       Match beginning of line (if at beginning of pattern)
XX    $       Match end of line (if at end of pattern)
XX    .       Match any character
XX    [..]    Match class of characters.  If first character following
XX            the [ is ^, match all BUT the range of characters.  A range
XX            of characters may be specified by separating them with a
XX            dash, e.g., [a-z].  The dash itself may be included as a class
XX            member by giving it as the first class char (e.g., [-a-z]).
XX    *       Match any number of preceding things (if does not follow
XX            *, ^ or $)
XX
XX    characters which have special meanings only in certain places in
XX    the pattern do not have that meaning elsewhere.  Special meaning
XX    may be turned off otherwise (except within a class) by escaping
XX    it with '\'.  The backslash may be entered into a pattern by
XX    doubling it.
XX    
XX    Version 1.0     12 March 1986
XX
XX    Paul DuBois
XX    Wisconsin Regional Primate Research Center
XX    1220 Capitol Court
XX    University of Wisconsin-Madison
XX    Madison, WI  53706
XX    
XX    UUCP: {allegra, ihnp4, seismo}!uwvax!uwmacc!dubois
XX*)
XX
XX
XXUses
XX    GrepPatStuff    (* pattern compilation and matching routines *)
XX    __StreamLib
XX    __DeskLib
XX    __ToolTraps
XX    __QuickDraw
XX    __OSTraps
XX    (*$U+*)
XX    uGrep   (* global constants, types, and variables *)
XX    ;
XX
XXLink
XX    GrepPatStuff
XX    __StreamLib
XX    __DeskLib
XX    __OSTraps
XX    : ;
XX
XX
XXConst
XX
XX    bufSiz = 512;
XX    curApplName = $910L;        (* location of name of current application *)
XX    defaultResID = -15552;      (* DRVR 26 base id *)
XX
XX
XX(*  menu item numbers  *)
XX
XX    itemAbout = 1;
XX    (* --- *)
XX    itemCount = 3;
XX    itemSearch = 4;
XX    itemPattern = 5;
XX    itemOutput = 6;
XX
XXVar
XX(*
XX    For a good time, declare thePort: WindowPtr (=GrafPtr!) and try to compile.
XX    Then look in uToolIntf under WindowPtr and sprout question marks.
XX*)
XX    thePort:    GrafPtr;
XX    teHand:     TEHandle;
XX    streamInfo: SFReply;
XX    theMenu:    MenuHandle;
XX    theMenuID:  Integer;
XX    resBase:    Integer;    (* base resource id *)
XX    matchType:  Boolean;    (* true: print lines w/pattern. false: inverse *)
XX    prtLineNum: Boolean;    (* print line numbers if true *)
XX    havePat:    Boolean;    (* whether have good pattern or not *)
XX    lineNum:    LongInt;
XX    paused:     Boolean;
XX    fileOpen:   Boolean;
XX    outFile:    Integer;
XX    outReply:   SFReply;
XX
XX    pauseCtl:   ControlHandle;
XX    cancelCtl:  ControlHandle;
XX    grepping:   Boolean;
XX
XX
XX
XXProc GrepState (val: Integer);
XX{
XX    HiliteControl (pauseCtl, val);
XX    HiliteControl (cancelCtl, val);
XX    grepping := !Boolean (val);
XX};
XX
XX
XX(*
XX    Cancel any current grep operation.
XX    Must not be called before InitStream.
XX*)
XX
XXProc StopGrep ();
XX{
XX    if grepping then
XX    {
XX        CloseStream ();
XX        GrepState (255);
XX    };
XX};
XX
XX
XXProc DrawStuff ();
XX{
XX    DrawControls (thePort);
XX    MoveTo (0, 24);
XX    LineTo (1000, 24);
XX    TEUpdate (teHand^^.viewRect, tehand);
XX};
XX
XX
XX
XXProc Alarm (mesg: PtrB);
XXVar
XX    result: Integer;
XX{
XX    ParamText (mesg, "", "", "");
XX    result := Alert (resBase+2, nil);
XX};
XX
XX
XXProc FileOutput ();
XXVar
XX    f: FInfo;
XX    result: OSErr;
XX    s: PtrB;
XX    p: ParamBlockRec;
XX    ok: Boolean;
XX{
XX    s := nil;
XX    if fileOpen then    (* close it *)
XX    {
XX        fileOpen := false;
XX        p.ioRefNum := outFile;
XX        result := PBGetFPos (p, false);
XX        p.ioMisc := p.ioPosOffset;
XX        result := PBSetEOF (p, false);
XX        result := FSClose (outFile);
XX        s := "Save Output...";
XX    }
XX    else
XX    {
XX        if EqualString ("Finder", curApplName, false, true) then
XX        {
XX            Alarm ("Not In Finder");
XX            return;
XX        };
XX        Toolbox($A9EA, 100, 70, "Write To...", "", nil, @outReply, 1);
XX        if outReply.good then
XX        {
XX            if GetFInfo (outReply.fName, outReply.vRefNum, @f) = noErr then  (* exists *)
XX            {
XX                if f.fdType <> PtrL (" TEXT"+2)^ then
XX                {
XX                    Alarm ("Not A TEXT File");
XX                    return;
XX                };
XX            }
XX            else    (* doesn't exist.  create it. *)
XX            {
XX                if Create (outReply.fName, outReply.vRefNum, PtrL (" Grep"+2)^,
XX                    PtrL (" TEXT"+2)^) <> noErr then
XX                {
XX                    Alarm ("Can't Create");
XX                    return;
XX                };
XX            };
XX            if _FSOpen (outReply.fName, outReply.vRefNum, @outFile, fsWrPerm)
XX                    <> noErr
XX                then Alarm ("Can't Open")
XX            else
XX            {
XX                fileOpen := true;
XX                s := "Stop Saving Output";
XX            };
XX        };
XX    };
XX    if s <> nil then
XX        SetItem (theMenu, itemOutPut, s);
XX};
XX
XX(*
XX    Add string to display area.  First insert it at the end.  Test if
XX    must scroll lines off top to get the new stuff to show up.  If yes,
XX    then do the scroll.  To keep from filling up the TERec, delete
XX    whatever got scrolled out of view every once in a while.  (The number
XX    of lines scrolled off the top to check for is arbitrary - I clobber
XX    stuff after every 25 lines.)  To avoid unnecessary redrawing, set to
XX    no clip before doing the delete (which would redraw) and the scroll
XX    back down (which would also redraw).
XX
XX    Also write string to output file if one is open.
XX*)
XX
XXProc DisplayString (theStr: PtrB);
XXVar
XX    dispLines: Integer;     (* number of lines displayable in window *)
XX    topLines: Integer;      (* number of lines currently scrolled off top *)
XX    scrollLines: Integer;   (* number of lines to scroll up *)
XX    height: Integer;
XX    r: Rect;
XX    len: LongInt;
XX{
XX    len := theStr[0];
XX    height := teHand^^.lineHeight;
XX    TESetSelect (32760L, 32760L, teHand); (* set to insert at end *)
XX    TEInsert (theStr+1, len, teHand);
XX    r := teHand^^.viewRect;
XX    dispLines := (r.bottom - r.top) / height;
XX    topLines := (r.top-teHand^^.destRect.top) / height;
XX    scrollLines := teHand^^.nLines - topLines - dispLines;
XX    if scrollLines > 0 then (* must scroll up *)
XX    {
XX        TEScroll (0, Integer (-height * scrollLines), teHand); (* scroll up *)
XX        topLines += scrollLines;
XX        if topLines > 25 then    (* keep TERec from filling up *)
XX        {
XX(*
XX    now clobber first line(s), and scroll back down to resync what will
XX    then be the first line.  Set clipping empty, so that the redraw from the
XX    delete and the scroll down will not be shown.
XX*)
XX            SetRect (r, 0, 0, 0, 0);
XX            ClipRect (r);
XX            TESetSelect (0L, LongInt (teHand^^.lineStarts[topLines]), teHand);
XX            TEDelete (teHand);
XX            TEScroll (0, Integer (height * topLines), teHand);
XX            ClipRect (thePort^.portRect);
XX        };
XX    };
XX    if fileOpen then
XX    {
XX        if FSWrite (outFile, @len, theStr+1) <> noErr then
XX        {
XX            Alarm ("Write Error (Closing File)");
XX            FileOutput ();
XX        };
XX    };
XX};
XX
XX
XXProc DisplayLn ();
XX{
XX    DisplayString ("\r");
XX};
XX
XX
XXProc DisplayLong (long: LongInt);
XXVar
XX    str: Byte[18];
XX    s: PtrB;
XX{
XX    s := str;
XX    RegCall (Trap $A9EE, s, , long, 0);     (* NumToString *)
XX    DisplayString (str);
XX};
XX
XX
XX
XXFunc GetStream (): Boolean;
XXVar
XX    s: Byte[5];
XX    i: Integer;
XX{
XX    GetStream := false;
XX    if OpenStream () = noErr then
XX    {
XX        GetStream := true;
XX        if thePort <> FrontWindow () then
XX            SelectWindow (thePort);
XX        GetStreamInfo (streamInfo);
XX        DisplayString (streamInfo.fName);
XX        DisplayString (" (");
XX        s[0] := 4;
XX        (*PtrL (@s[1])^ := streamInfo.fType;*)  (* doesn't work - odd addr! *)
XX        loop ( , i:=0, ++i, i > 3)
XX            s[i+1] := (PtrB (@streamInfo.fType))[i];
XX        DisplayString (s);
XX        DisplayString (" file)\r");
XX    };
XX    DrawStuff ();
XX};
XX
XX(*
XX    Display lines matching (or not matching) pattern.  This is called to
XX    get a line at a time from _Main.  Mouse clicks in _Mouse control the
XX    state of the pause variable.
XX*)
XX
XXProc GrepLine ();
XXVar
XX    buf: block[bufSiz];
XX{
XX    if !paused then
XX    {
XX        if StreamGetS (buf) = nil then
XX        {
XX            StopGrep ();
XX        }
XX        else
XX        {
XX            ++lineNum;
XX            PToCStr (buf);
XX            if match (buf) = matchType then
XX            {
XX                if prtLineNum then
XX                {
XX                    DisplayLong (lineNum);
XX                    DisplayString (": ");
XX                };
XX                CtoPStr (buf);
XX                DisplayString (buf);
XX                DisplayLn ();
XX            };
XX        };
XX    };
XX};
XX
XX
XX
XX(*
XX    Catch mouse down events, and interpret if window grow event.  This is
XX    difficult to test inside of Rascal, since it will catch mouse downs
XX    in the grow region and size the window itself.  Can't use FindWindow
XX    in _Event when running as a DA, since it returns inSysWindow for a
XX    part code, not inGrow!
XX*)
XX
XXProc _MOUSE (x, y: Integer);
XXVar
XX    ctl: ControlHandle;
XX    thePt: Point;
XX    r: Rect;
XX{
XX    thePt.h := x;
XX    thePt.v := y;
XX    r := thePort^.portRect; (* see the mouse was pressed in grow region *)
XX    r.left := r.right - 15;
XX    r.top := r.bottom - 15;
XX    if PtInRect (thePt.vh, r) then
XX    {
XX        LocalToGlobal (@thePt);
XX        SetRect (r, 170, 60, 512, 342);
XX        thePt.vh := GrowWindow (thePort, thePt.vh, r);
XX        SizeWindow (thePort, thePt.h, thePt.v, true);
XX        r := thePort^.portRect;
XX        ClipRect (r);
XX(*
XX    Reset the text viewRect.  It's not necessary to reset the destRect,
XX    since only the top and left are used, and they haven't changed.
XX*)
XX        r.top += 25;
XX        r.left += 6;
XX        teHand^^.viewRect := r;
XX    }
XX    else if FindControl (thePt.vh, thePort, @ctl) then
XX    {
XX        if TrackControl (ctl, thePt.vh, nil) then
XX        {
XX            if ctl = cancelCtl then
XX            {
XX                StopGrep ();
XX            }
XX            else if ctl = pauseCtl then
XX            {
XX                if paused then
XX                    SetCTitle (pauseCtl, "Pause")
XX                else
XX                    SetCTitle (pauseCtl, "Resume");
XX                paused := !paused;
XX            };
XX        };
XX    };
XX};
XX
XX
XXProc Wc ();
XXVar
XX    lines, nonEmptyLines, words, chars: LongInt;
XX    inToken: Boolean;
XX    c, lastc: Integer;
XX{
XX    lines := 0;
XX    nonEmptyLines := 0;
XX    words := 0;
XX    chars := 0;
XX    inToken := false;
XX    loop (, lastc := '\r', lastc := c,)
XX    {
XX        c := StreamGetC ();
XX        if c = -1 then break;   (* eof *)
XX        ++chars;
XX        case c of
XX            '\r':
XX            {
XX                ++lines;
XX                if lastc <> '\r' then
XX                    ++nonEmptyLines;
XX                inToken := false;
XX            };
XX            ' ',
XX            '\t': inToken := false;
XX            otherwise
XX                if inToken = false then
XX                {
XX                    ++words;
XX                    inToken := true;
XX                };
XX        end;
XX    };
XX    if (lastc <> '\r') then    (* in case of missing cr on last line *)
XX    {
XX        ++lines;
XX        ++nonEmptyLines;
XX    };
XX    DisplayLong (chars);
XX    DisplayString (" Chars, ");
XX    DisplayLong (words);
XX    DisplayString (" Words, ");
XX    DisplayLong (lines);
XX    if streamInfo.fType = PtrL (" TEXT"+2)^ then
XX        DisplayString (" Lines")
XX    else
XX    {
XX        DisplayString (" Paragraphs (");
XX        DisplayLong (nonEmptyLines);
XX        DisplayString (" non-empty)");
XX    };
XX    DisplayLn ();
XX};
XX
XX
XXProc _INIT ();
XXVar
XX    r: Rect;
XX{
XX    GetPort(@thePort);
XX
XX(*  adapt to environment - am I a desk accessory or not?  *)
XX
XX    theMenuId := DAMenuInit ();
XX    resBase := defaultResID;
XX    if IsDARun () then
XX    {
XX        resBase := GetResIDBase ();
XX    };
XX
XX    theMenu := NewMenu (theMenuId, "Grep-Wc");
XX    InsertMenu (theMenu, 0);
XX    AppendMenu (theMenu,
XX    "About Grep-Wc;(-;Count...;Search...;Set Pattern...;Save Output...");
XX    DrawMenuBar ();
XX
XX    InitStream ();              (* set up for stream input *)
XX    InitPat ();                 (* initialize pattern *)
XX    fileOpen := false;          (* no output file currently *)
XX
XX(*  Initial option settings  *)
XX
XX    matchType := true;          (* print lines with pattern *)
XX    prtLineNum := false;        (* don't print line numbers *)
XX
XX(*  Create TERec and build controls  *)
XX
XX    r := thePort^.portRect;
XX    r.top += 25;            (* leave room for buttons *)
XX    r.left += 6;
XX    teHand := TENew (r, r);
XX    teHand^^.crOnly := -1;  (* no word wrap *)
XX    SetRect (r, 5, 2, 85, 22);
XX    pauseCtl :=
XX        NewControl (thePort, r, "Pause", true, 0, 0, 0, pushButProc, nil);
XX    OffSetRect (r, 90, 0);
XX    cancelCtl :=
XX        NewControl (thePort, r, "Cancel", true, 0, 0, 0, pushButProc, nil);
XX
XX    GrepState (255);    (* set grepping false, inactivate buttons *)
XX    DrawStuff ();
XX};
XX
XXProc _HALT ();
XX{
XX    CloseStream ();         (* close any open input file *)
XX    if fileOpen then        (* close output file if one is open *)
XX        FileOutPut ();
XX    KillControls (thePort); (* toss controls *)
XX    TEDispose (teHand);     (* toss text *)
XX    DeleteMenu (theMenuID); (* toss menu *)
XX    DisposeMenu (theMenu);
XX    DrawMenuBar ();
XX};
XX
XX
XXProc _UPDATE();
XX{
XX    DrawStuff ();
XX};
XX
XX
XXProc _MENU (id, item: Integer);
XX{
XX    case item of
XX        itemAbout:  item := Alert (resBase+1, nil);
XX        itemCount:
XX        {
XX            StopGrep ();        (* terminate any ongoing grep operation *)
XX            if GetStream () then
XX                Wc ();
XX        };
XX        itemSearch:
XX        {
XX            StopGrep ();        (* terminate any ongoing grep operation *)
XX            if !havePat then
XX                GetGrepPat ();
XX            if (* now *) havePat then
XX                if GetStream () then    (* do grep setup *)
XX                {
XX(*
XX    Don't comment this section out if you don't want the user
XX    to be able to grep his current output file.
XX                    if fileOpen then
XX                    {
XX                        if EqualString (outReply.fName, streamInfo.fName,
XX                                        false, true)
XX                        and (outReply.vRefNum = streamInfo.vRefNum) then
XX                        {
XX                            Alarm ("Can't Grep Output File");
XX                            return;
XX                        };
XX                    };
XX    end commenting out
XX*)
XX                    lineNum := 0;
XX                    paused := false;
XX                    SetCTitle (pauseCtl, "Pause");
XX                    GrepState (0);  (* turn controls on, grepping true *)
XX                };
XX        };
XX        itemPattern: GetGrepPat ();
XX        itemOutput: FileOutput ();
XX    end;
XX};
XX
XX
XXProc _MAIN ();
XX{
XX    if (thePort = FrontWindow ()) and grepping then GrepLine ();
XX};
SHAR_EOF
if test 14893 -ne "`wc -c Grep-Wc.src`"
then
echo shar: error transmitting Grep-Wc.src '(should have been 14893 characters)'
fi
echo shar: extracting Grep-Wc.rsrc.Hqx '(1535 characters)'
sed 's/^XX//' << \SHAR_EOF > Grep-Wc.rsrc.Hqx
XX(This file must be converted with BinHex 4.0)
XX
XX:$%GbCA!Y9f-ZFR0bB`"549K&8N008!#3#!422H%!N!3"!*!$!p%!!!,4!*!$IN(
XXX!J!J#0#I)%![#"!Z!!JJAa#!3H`%!P*3-#`%!NM!,`""l!)!)!M3Rb"!,`J`2!!
XX!)&m3J%jH)&rHr!!#6Y"19[rq3H`%!P*33HlrrLm)-#`%!L"I-)"J!!!H3HlrrP0
XX3-#`%"$m!-#lrrV"IAm"%!%S!CJ!!1M!Zrrj)`#m!3H`#!#!)d*mJ3#m)-$`!!6m
XX!-#lrrT!!AdM!,`""l!)!)!M3Rb"!%"!JAa#!B!$rVM!X"!4)`#m!3H`#!#!)d*m
XXJ3#m)-$`!"L"I%)""l!3',`J`2!!!)&m`J%jH6R9"l!3%,`J`,!3#)&m`J%(X"!B
XX!N!-9!#J!-J#L!E`!!3#3#-0!!*!%Y!!'!*!&3!%c!&3"E`3#6dX!N!9D!6-!EJ&
XX["!C$B@jMC@`!N!8'!!N!&`"$L!K3BA4dCA*Z1J#3"4d!#!!Y!AQ3!!#3"MN!"J"
XX0!0N''%aTEQ9c)%0[ER4KD@jTEQFJ8'&dG'9bEJ#3"8i!"J"L!0J'(%aTEQ9c)%j
XX[G#"$EfjdB@PZD@jR)&"KG(4PFQi!N!9M!!B!G`$B"3a-D@jP)%jeE@*PFR-!N!-
XX-!#`!%!$N!CE$384%!!!"RJ!%!*!&P!!b!+J!EJ3#6dX!N!8)!!F!KJ#BL(T(FQ9
XX`)#mJ9fpbC#"$Eh9ZG!ef-5i`)#!a-b"0BA*MD#!a16Jf$5K3G@*XD@-J4'pYB@P
XXZ+3d08'&eE#"%G8*[DA-0-6)b-#"$BA"TG'pX)%0[GA*d$8eKC'PcEfiJ9dNJ06-
XXh-$B0999$8$SJGAGYB@0M)@4eBQpTF`#3"4i![J#Z!0D)%&i0*!dZ$9XZ,Pd0$5S
XX0$9`!N!8H!0S!VJ'&L,"0BA4MD#"cG'&bG#"[CL"XD@jP$8eKG'0S)'9ZC#"[CL"
XXXD@jP$8eKG'0S)'&ZH5"MD'&bB@0dCA)06@&dBfJJB@jj)'0SBA*KBh4PFL"LCA4
XXhC@9Z)'*bB@0VCA4c$8eKG'0S)'&ZH5"ZG@eLCA)JEfBJG'KP)("bCACTEh9c)(4
XXSD@jR$94eFQiJEfCQ)(0`C@0TB@`JE@9KEQPZCb"[CL"ZCAKd)'0SBA*KBh4PFJ#
XX3"3J![J!D!A1)'P0`C@0TB@`J8'&dG'9bEL"$D'&bB@0dCA*cB@0dCA*cBQaTBb"
XXNEfeKD@iTG@*[DA-+!*!$)J!"!*!&8`"2!'F!L`3#6dX!N!8(!!B!4`#3!)J#AM!
XX!N!--!$)!0!#P!-M$3N4%!!!"!*!$!p%!!!,4!*!$IJ!!c"`!2J#3!a`!IJ!#4%P
XX86!!#!"T%6%p(!*!$2N&-8P3!!3"+`d,rrb!!!TX!N!6$3Irr)!!!i3!"-(,$32r
XXr)!!!'3#3"-0!rrmJ!*!(`d,rrb!!!X%!!5YS`d(rrb!!!0%!!5YXSC):
SHAR_EOF
if test 1535 -ne "`wc -c Grep-Wc.rsrc.Hqx`"
then
echo shar: error transmitting Grep-Wc.rsrc.Hqx '(should have been 1535 characters)'
fi
echo shar: extracting AddRes.src '(5070 characters)'
sed 's/^XX//' << \SHAR_EOF > AddRes.src
XXProgram AddRes;
XX
XXUses
XX    __ToolTraps
XX    __QuickDraw
XX    __OSTraps
XX    __DeskLib
XX    (*$U+*)
XX    uOSIntf
XX    uToolIntf
XX    uPackIntf
XX    ;
XX
XXLink
XX    __DeskLib
XX    __OSTraps
XX    __NoSysCall
XX    : ;
XX
XX
XXVar
XX    buttonTitle: PtrB;
XX
XX
XXProc PrintResType (resType: ResType);
XXVar
XX    i: Integer;
XX{
XX    loop (, i := 0, , ++i > 3)
XX    WriteChar (Integer (PtrB (@resType)[i]));
XX};
XX
XXProc CopyResources (srcResFile, dstResFile: Integer);
XXVar
XX    curRF: Integer;
XX    numTypes: Integer;
XX    numRes: Integer;
XX    resHand: Handle;
XX    resType: ResType;
XX    resId: Integer;
XX    resName: str255;
XX    i, j: Integer;
XX{
XX    WriteString ("Source, dest files ");
XX    WriteInt (srcResFile);
XX    WriteInt (dstResFile);
XX    WriteLn ();
XX    numTypes := CountTypes ();
XX    SetResFileAttrs (srcResFile, 128);  (* source map read only *)
XX    SetResPurge (true);
XX    loop (numTypes > 0, i := numTypes, , --i < 1)
XX    {
XX        GetIndType (@resType, i);   (* get name of resource type *)
XX        numRes := CountResources (resType);
XX        loop (numRes > 0, j := 1, , ++j > numRes)
XX        {
XX            curRF := CurResFile ();
XX            SetResLoad (false);
XX            resHand := GetIndResource (resType, j);
XX            SetResLoad (true);
XX            if HomeResFile (resHand) = srcResFile then
XX            {
XX                LoadResource (resHand);
XX                GetResInfo (resHand, @resId, @resType, resName);
XX                UseResFile (srcResFile);
XX                RmveResource (resHand);
XX                UseResFile (dstResFile);
XX                AddResource (resHand, resType, resId, resName);
XX                WriteString ("AddResource ");
XX                WriteInt (ResError());
XX                WriteLn ();
XX                HPurge (resHand);
XX                UseResFile (curRf);
XX                WriteString ("Added ");
XX                PrintResType (resType);
XX                WriteInt (resId);
XX                WriteChar (' ');
XX                WriteString (resName);
XX                WriteLn ();
XX            };
XX        };
XX    };
XX};
XX
XXFunction GFFilter (theItem: integer; theDialog: Ptrl): Integer; Clean;
XXvar
XX    itemNo: integer;
XX    itemType: integer;
XX    itemHandle: Handle;
XX    rect: Integer[4];
XX{
XX    DAClean (false);
XX    if theItem = -1 then    (* change name of "Open" button *)
XX    {
XX        GetDItem (theDialog, 1, @itemType, @itemHandle, rect);
XX        SetCTitle (itemHandle, buttonTitle);
XX    };
XX    GFFilter := theItem;
XX};
XX
XX
XXFunc GetFile(reply: ^SFReply; btnTitle: PtrB): Boolean;
XX{
XX    buttonTitle := btnTitle;
XX    Toolbox ($A9EA, 100, 50, " ", nil, -1, nil, GFFilter, reply, 2);
XX    GetFile := reply^.good;
XX};
XX    
XXFunc myGetVol (): Integer;
XXVar
XX    p: ParamBlockRec;
XX    result: OSErr;
XX{
XX    p.ioCompletion := nil;
XX    p.ioNamePtr := nil;
XX    result := PBGetVol (p, false);
XX    myGetVol := p.ioVRefNum;
XX};
XX
XXProc mySetVol (v: Integer);
XXVar
XX    p: ParamBlockRec;
XX    result: OSErr;
XX{
XX    p.ioCompletion := nil;
XX    p.ioNamePtr := nil;
XX    p.ioVRefNum := v;
XX    result := PBSetVol (p, false);
XX};
XX
XX
XXFunc OpenResourceFile (name: PtrB; vRefNum: Integer): Integer;
XXVar
XX    curVol: Integer;
XX{
XX    curVol := myGetVol ();
XX    mySetVol (vRefNum);
XX    OpenResourceFile := OpenResFile (name);
XX    mySetVol (curVol);
XX};
XX
XX
XXProc CreateResourceFile (name: PtrB; vRefNum: Integer);
XXVar
XX    curVol: Integer;
XX{
XX    curVol := myGetVol ();
XX    mySetVol (vRefNum);
XX    CreateResFile (name);
XX    mySetVol (curVol);
XX};
XX
XX
XXProc _Init ();
XXVar
XX    srcResFile, dstResFile: Integer;
XX    srcReply, dstReply: SFReply;
XX    thePort: PtrL;
XX{
XX    DAClean (true);
XX    GetPort (@thePort);
XX    TextFont (0);
XX    TextSize (0);
XX    MoveWindow (thePort, 4, 235, false);
XX    SizeWindow (thePort, 504, 100, false);
XX    WriteString ("\nSelect the file you wish to copy resources FROM.\n");
XX    if GetFile (@srcReply, "Copy From") then
XX    {
XX        srcResFile := -1;
XX        WriteString ("Now select the file you wish to copy resources TO.\n");
XX        if GetFile (@dstReply, "Copy To") then
XX        {
XX            srcResFile := OpenResourceFile (srcReply.fName, srcReply.vRefNum);
XX            if srcResFile = -1 then
XX                WriteString ("Can't open input file.\n")
XX            else
XX            {
XX                dstResFile := OpenResourceFile (dstReply.fName,
XX                                                dstReply.vRefNum);
XX                if dstResFile = -1 then
XX                {
XX                    WriteString ("Creating resource fork - output file.\n");
XX                    CreateResourceFile (dstReply.fName, dstReply.vRefNum);
XX                    dstResFile := OpenResourceFile (dstReply.fName,
XX                                                      dstReply.vRefNum);
XX                    if dstResFile = -1 then
XX                        WriteString ("Couldn't create resource file.\n");
XX                };
XX                if dstResFile <> -1 then
XX                {
XX                    CopyResources (srcResFile, dstResFile);
XX                    CloseResFile (dstResFile);
XX                };
XX            };
XX        };
XX        if srcResFile <> -1 then
XX            CloseResFile (srcResFile);
XX    };
XX    ReqHalt ();
XX};
SHAR_EOF
if test 5070 -ne "`wc -c AddRes.src`"
then
echo shar: error transmitting AddRes.src '(should have been 5070 characters)'
fi
#	End of shell archive
exit 0

-- 
                                                                    |
Paul DuBois     {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois        --+--
                                                                    |
                                                                    |