!Utility to search text of file(s) for keystring.

! MDP Feb/1984.
!JHB hacked it Sep 1984. Commented out stats, added
!option to display text centred with newlines replaced by '_' and tidied up a bit
!JHB at it again Oct 84 - added output file option
!JHB at it again May 85 - added "suppress output" option

own  string  (255) Wild File     = "",
{{                 In file       = "",
                   Key = ""
own  byteinteger   disflag       = 0

include  "inc:util.imp"
include  "inc:fs.imp"
include  "inc:fsutil.imp"

begin 
   string  (31) array  File Names (1 : 110)
   integer  Number of Files = 0
   string  (63) This File, A, B, Base File Name, Directory, Line, outfile
   integer  Ptr 1, Ptr 2, Index, outstream
   integer  Number Found = 0, Flag = 0
   integer  CPU 0 = 0, CPU 1 = 0, CPU 2 = 0, Call = 0

   routine  Load Directory (string  (7) Directory)

      string  (127) Line

      on  0,1,2,3,4,5,6,7,8,9,10 start 
         -> End Load
      finish 

      Directory = Directory . ":" if  Directory # ""
      Open Input (1, Directory."Directory");   Select Input (1)

      Number of Files = 0
      cycle 
         Read Line (Line)
         Number of Files = Number of Files + 1
         File Names (Number of Files) = Line
      repeat 

 End Load:
      if  Number of Files = 0 start 
         Printline("SEARCH : Can't load directory - ".Event_Message)
         stop 
      finish 
      Close Input
      Select Input (0)
   end 

   predicate  Match String (integer  Source, Pattern, Length)

      label  False, Case Ok

{ Call = Call + 1
      true  if  Length = 0

      *Move.L Source,  A0
      *Move.L Pattern, A1
      *Move.L Length,  D0

   Compare:
      *Move.B (A0)+, D1
      *Cmp.B  #'A', D1
      *Blt    Case Ok
      *Cmp.B  #'Z', D1
      *Bgt    Case Ok
      *Or.B   #' ', D1
   Case Ok:
      *Move.B (A1)+, D2
      *Cmp.B  D1,D2
      *Bne    False
      *Subq   #1, D0
      *Bne    Compare
!      *DBne   D0, Compare

!      Number Found = Number Found + 1
      true 
   False:
      false 
   end 

   routine  Display String (integer  name  Index,
                            integer  Start, Finish,
                            string  (31) File Name)

      own  string  (31) Last File = ""
      integer  Sym, From, To, Count

      if  Last File # File Name start 
         New Line
         Printline("*** ".File Name." :***********************************")
         New Line
         Last File = File Name
      finish 

      if  disflag = 0 start  
         !Display the line containing the text. Woe betide if it's long.

         From = Index
         From = From - 1 while  From > Start  and  Byte Integer (From) # Nl
         From = From + 1 if  from # start

         To = Index
         To   = To   + 1 while  To   < Finish and  Byte Integer ( To ) # Nl

         if  to - from > 79 start  ;!Very long line
            from = index - 39 if  index - 39 > from
            to = from + 80 if  from + 80 < to
         finish 

         Index = To

      elseif  disflag=1
         from = index - 39; to = index + 39
         index = to

      else  ;!Suppress printing
         return 

      finish 

      from = start if  from < start; to = finish if  to > finish
      for  sym = from, 1, to-1 cycle 
         if  ' ' <= byteinteger(sym) <= 16_7e then  printsymbol(byteinteger(sym)) else  c 
         printsymbol('_')
      repeat 
      newline
   end 

   routine   Search File (string  (31) Directory, File)

      integer  File Start, Len, File End
      integer  Sym, Upper, Index
      integer  F Start

      File = Directory .":". File if  Directory # ""
      Connect File (File, 0, File Start, Len)

!      CPU 2 = CPU Time
      File End = File Start + Len - 1
      Upper = File End - length(key) + 1
      Index = File Start

      while  Index < Upper cycle 
         if  Match String (Index, addr(key)+1, length(key)) start 
            Display String (Index, File Start, File End, File)
            exit  if  disflag=2
         else 
            Index = Index + 1
         finish 
      repeat 
!      CPU 2 = CPU Time - CPU 2
       heapput(file start)
   end 

   on  3,4,9 start 
      -> Deleted file if  Flag = 1
      newline
      Stop 
   finish 

   outfile = ":"; wild file = "*.*"

{{ define param ("IN", infile, 0)
   Define Param ("Wildfile", Wild File, 0)
   Define Param ("Searchstring", Key, pam nodefault)
   Define enum Param ("Line,Centred,None", disflag, 0)
   define param("Output", outfile, pam newgroup)
   Process Parameters (CLI Param)

   Base File Name = Wild File
{{ open input(1, infile) %if infile # ""
{{ Prompt ("File:   ")
{{ Read Line (Base File Name) %while Base File Name = ""
{{ Prompt ("String: ")
{{ Read Line (Key) %while Key = ""
{{ close input %if infile # ""

   !Ditch quotes if he quoted it and map to lower case
   Key = Sub String (Key, 2, Length (Key)) if  Charno (Key, 1) = '"'
   length(Key) = length(Key) - 1 if  charno(key, length(key)) = '"'
   if  length(key) = 0 then  printstring("SEARCH: *** Null search string supplied ***
") and  stop 
   to lower(key)

   !Haul in USER:DIRECTORY special file
   Directory = "" unless  Base File Name -> Directory .(":"). Base File Name
   Load Directory (Directory)

   Ptr 1 = 1; Ptr 2 = 1
   while  Ptr 1 <= Number of Files cycle 
      This File = File Names (Ptr 1)
      if  Matches (This File, Base File Name) start 
         if  Base File Name = "*" start 
            Ptr 1 = Ptr 1 + 1 and  continue  if  This File -> A .("."). B
         finish 
         File Names (Ptr 2) = This File
         Ptr 2 = Ptr 2 + 1
      finish 
      Ptr 1 = Ptr 1 + 1
   repeat 

   Number of Files = Ptr 2 - 1
   if  Number of Files = 0 start 
      Printline("No files matched file specification.")
      stop 
   finish 

!!?   close output
   if  outfile="" or  outfile= ":" then  outstream=0 elsestart 
      printline("Recording output in ".outfile)
      outstream=2
      open output(2, outfile); selectoutput(2)
   finish 

   Index = 1
   CPU 0 = CPU Time
   while  Index <=Number of Files cycle 
      Flag = 1
      Search File (Directory, File Names (Index))
Deleted File:
      Flag = 0
      CPU 1 = CPU 1 + CPU 2
      Index = Index + 1
   repeat 

   New Line
close output and  selectoutput(0) if  outstream#0
end  of  program