!**********************************************************************
!**
!** A P M    C L E A N    -  An implementation of VAX Clean for the APMs
!**
!**  7/3/84 AJS - First Implementation - no cross directory ops
!**         MDP - Added Hexdump & Vecce
!** 20/4/84 AJS - Added IE properly & added wildcard filenames
!** 24/7/84 JGH - Fixed a bug were valid permissions were flagged as invalid!
!**
!**

conststring (8) version = "24/07/84"

include  "inc:util.imp"
include  "inc:fs.imp"
include  "inc:fsutil.imp"
include  "ie:ie.inc"
include  "inc:ecce.imp"
include  "inc:vtlib.imp"

Owninteger  eod=0
Ownstring (63) fsp
Ownstring (6) user
owninteger  depth = 0

Routine  Skip Blanks (string (*)name  it)

   return  if  length(it) = 0
   it = substring(it,2,length(it)) while  charno(it,1) = 32 and  it#""
end 

Routine  Truncate Blanks (string (*)name  it)

   return  if  length(it) = 0
   length(it) = length(it)-1 while  charno(it,length(it)) =' ' and  length(it)#0
End 
   

Routine  Print Filename (string (12) f)

   spaces (15-length(f))
   printstring (f)
   space
end 

Routine  Type File (string (63) file,Integer  n)

   integer  sym,m=0

   on  0,3,4,9 start 
      close input
      select input (0)
      if  event_event = 9 and  event_sub = 3 start 
         printline (event_message)
         return 
      finish 
      newline
      newline
      return 
   Finish 

   open input (2,file)
   while  m # n cycle 
      read symbol (sym)
      print symbol (sym)
      m = m + 1 if  sym = nl
   repeat 
   close input
   select input (0)
end 

!ECCExx:    Implementation of ECCE for 2900/EMAS, VAX/VMS and APM
!  Revised specification (1981/82) including video support.
!  Hamish Dewar   Edinburgh University Computer Science Department
!

constinteger  MAXNAME=127
routine  Ecce (string  (255) Param Line)

  integer  i,same
   string (255) heading

   ownrecord (edfile) MAIN=0,SEC=0
   ownstring (maxname) OUTNAME
   !
   routine  SET PARAMETERS(string (255) ecce in)
   
      if  ecce in -> ecce in .("/"). out name start 
         main_name = ecce in
      else 
         main_name = ecce in
         main_name = "" if  main_name = ".N"
         outname = main_name
      finish 
      outname = "" if  outname = ".N"
   end ;  !SET PARAMETERS

   on  0 start 
      select input (0)
      select output (0)
{}    pop frame; pop frame
{}    set mode(0)
!!    pop window; pop window
!!    set video mode (0)
      printsymbol (27) ; printsymbol ('>')
      newline
      return 
   finish 

   Set parameters (param line)
   same = 0;  same = 1 if  outname = main_name
   main_flag = 32768;  !plus extra
   connect edfile(main)
   -> stop if  main_flag # 0

   if  outname # "" start 
      if  main_name # "" start  
        heading = "Editing  ".main_name
        heading = heading."  to  ".outname if  same = 0
      finish  else  start 
        heading = "Creating  ".outname
      finish 
   finish  else  start 
      main_change = -1
      heading = "Showing  ".main_name
   finish 

   main_lim1 = main_start1;  sec_lim1 = sec_start1
   main_fp = main_start2;  main_change = 16_7FFFFFFF
   edi(main,sec,heading)

!MAIN_FLAG is negative if edit abandoned
!MAIN_CHANGE is untouched (neg or zero) if no changes

   if  main_flag < 0 or  (main_change = 16_7FFFFFFF and  same # 0) start 
     print string(" File unchanged")
     main_change = -1
   finish 
 
   if  main_change >= 0 start ;  !file to be written
     sec_name = main_name;  main_name = outname
     disconnect edfile(main)
     printstring(sec_name."  edited to  ".main_name)
   finish 
   newline
stop:
end 

routine  Call IE (string  (80) fname)
   string  (255) Profile = ""
   integer  sl, sc

   on  0, 3, 4, 9, abort start 
      Reset Terminal
      select input (0); select output (0)
      printline("IE fails ".event_message)
      return 
   finish 

   terminal serial number = default terminal
   journal file = default journal
   Set Up Terminal
   sl = 1
   sc = 1
   IE Editor (fname, fname, 0, 23, sl, sc, default profile, c 
              default keyboard, reset heap ! confirm)
!!   *move heapnow,d6
   Reset Terminal
   select input (0) ; select output (0)
   New Line
end 

routine  Count Lines (string (63) file)

   integer  sym,m=0

   on  0,3,4,9 Start 
      close input 
      select input (0)
      if  event_event=9 and  event_sub=3 start 
         printline (event_message)
         return 
      finish 
      unless  event_event = 0 Start 
          Printstring ("File is ")
          Write (m,0)
          printline (" lines long")
      Finish 
      return 
   Finish 
      
   open input (2,file)
   cycle 
      read symbol (sym)
      m = m + 1 if  sym = nl
   repeat 
End 

routine  Dump file (string  (255) File, integer  Lines)

   byte  array  Line (0:1023)
   integer  Line Length, Line Number = 0
   integer  Sym, Offset = 0

   routine  Dump Line
      
      integer  Start, T Start, T End
      integer  I, Sym

      Line Number = Line Number + 1
      Print String ("Line ")
      Write (Line Number, 0)
      New Line
      Start = 0

      cycle 
         T Start = Start
         if  Line Length > 16 start 
            T End = T Start + 15
            Start = Start + 16
            Line Length = Line Length - 16
         else 
            T End = Start + Line Length - 1
            Line Length = 0
         finish 

         Phex (Offset)
         Print String (": ")
         Offset = Offset + (T End - T Start + 1)

         for  I = T Start, 1, T End cycle 
            P Hex2 (Line (I))
            Space
         repeat 
 
         Spaces (48 - 3 * (T End - T Start + 1))
         Print String ("| ")

         for  I = T Start, 1, T End cycle 
            Sym = Line (I)
            Sym = Sym & 16_7f
            if  Sym < ' ' or  Sym = 16_7f then  Sym = '_'
            Print Symbol (Sym)
         repeat 
         New Line
      repeat  until  Line Length = 0
   end 

   on  0,3,4,9 start 
      if  event_event=9 and  event_sub = 3 start 
         printstring (event_message)
         newline
      else  if  event_event = 0
         newline
      Finish 
      -> End Dump
   finish 

   Open Input (2, File)
   Select Input (2)

   while  Lines # 0 cycle 
      Line Length = 0
      cycle 
         Read Symbol (Sym)
         Line (Line Length) = Sym
         Line Length = Line Length + 1
         if  Line Length = 1024 start 
            Read symbol (Sym) until  Sym = 'Nl'
         finish 
      repeat  until  Sym = Nl

      Dump Line
      Lines = Lines - 1
   repeat 

End Dump:
   Close Input
   Select Input (0)
   Print String ("File ".File." Dumped, ".I to S(Line Number,0)." Lines")
   New Line
end 

Routine  Print Help
!   printline ("A <file> to append the file to another file")
   printline ("C <file> to copy the file into another file")
   printline ("D to delete the file")
   printline ("E to quit the program")
   printline ("F <filespec> to change temporarily to a new filespec")
   printline ("H to type this information")
   printline ("I to display file details")
   printline ("IE to edit the current file using IE")
   printline ("K to count the number of lines in the file")
!   printline ("L to list the remaining files in the current directory")
   printline ("N <newfile> to rename the file to newfile")
   printline ("P to change the file protection")
   printline ("Q to quit the program")
   printline ("R to restart from the top")
   printline ("T <n> to type out the first n lines of the file")
   printline ("V to edit the current file using VECCE")
   printline ("X <n> to hexdump the first n records of the file")
   printline ("<cr> to go on to the next file")
End 

Routine  Open Directory

   on  3,4,9 start 
      eod = 1
      select input (0)
      return 
   finish 

   Open Input (1,user.":directory")
end 

Routine  Get Next File

   on  3,4,9 start 
      eod = 1
      select input (0)
      return 
   finish 

   Select Input (1)
   Read Line (fsp)
   Select Input (0)
End 
   
routine  parm Complain
   printstring ("Missing parameter");newline
End 

Integerfn  toint (String (80) s)

   on  3 start 
      result  = -1
   finish 

  result  = Stoi (s)
end 

Routine  Do A File (String (63) thisfile)

   string  (255) Fcomms
   string (80) line,com
   string (63) fname1,fname2
   byte  c,fp
   integer  n1
   switch  sw ('A':'Z')

   Integerfn  Get Integer
      integer  i
      if  fp = 0 start 
         if  length (line) > 1 start 
            i = toint(substring(line,2,length(line)))
         else 
            i = 999999
         finish 
      else 
         i = toint (fname1)
      finish 
      result  = i
   end 

   on  3,4,9 start 
      if  event_sub = 3 Start 
         printline (event_message)
         -> again
      finish 
      newline
      stop 
   finish 

again:
   Cycle 
      to Lower(thisfile)
      prompt("")
      print filename (thisfile)
      Read Line (line)
      Skip Blanks (line)
      to Upper(line)
      return  if  line = ""
      if  line -> line.(" ").fname1 start 
         skipblanks (fname1)
         truncateblanks (fname1)
         if  fname1 -> fname1.(" ").fname2 start  ; finish 
         fp = 1
      Else 
         fp = 0 
      Finish 
      fp = 0 if  fname1=""
      c=charno(line,1)
      -> sw (c) if  'A'<=c<='Z'

sw(*): Printstring ("Unrecognised command ")
       printsymbol (c)
       Newline
       Newline
       -> Help

sw('C'):
       Parm Complain and  Continue  if  fp = 0
       to lower(fname1)
       copy (thisfile,fname1)
       printline ("Copied ".thisfile." to ".fname1)
       return 

sw('D'):
       if  charno (line,length(line)) = '!' Start 
          Delete (thisfile)
          printline ("Deleted ".thisfile)
       Else 
          printline  ("Use D!")
          continue 
       Finish 
       return 

sw('E'):
       -> sw ('Q')

sw('F'):
       Parm Complain and  Continue  if  fp = 0
       if  exists (fname1) start 
          depth = depth + 1
          Do a File (fname1)
          depth = depth - 1
          Continue 
       Else 
          printline ("File ".fname1." does not exist")
       Finish 
       Continue 
 
sw('H'):
Help:
       Print Help
       Continue 

sw('I'):
       if  Length (Line) = 2 and  Charno (Line, 2) = 'E' start 
          Call IE (this file)
       else  if  length (Line) = 1
          length (FComms) = fcommr ('N'<<8, This File, Charno (FComms, 1), 255)
          Print Line (FComms)
       else 
          printline ("Not Implemented.")
       finish 
       continue 

sw('K'):
       Count Lines (thisfile)
       Continue 

sw('N'): 
       Parm Complain and  continue  if  fp = 0 
       to lower(fname1)
       rename (thisfile,fname1)
       printline ("Renamed ".thisfile." to ".fname1)
       return 

sw('P'):
       Parm Complain and  Continue  if  fp = 0
       to Upper(Fname1)
       unless  1 <= length(fname1) <= 3 start 
           printline ("Faulty permission")
           Continue 
       Finish 
       permit (thisfile,fname1)
       Continue 

sw('Q'): 
       eod = 1
       Return 

sw('R'):
       If  depth = 0 start 
          printline ("Restarting from top")
          Open Directory
          return 
       else 
          printline ("Can't restart within recursive call")
       finish 
       Continue 

sw('T'):
       n1 = get integer
       if  n1 < 0 start 
          printline ("Invalid integer specified")
       Else 
          n1 = 999999 if  n1=0
          type file (thisfile,n1)
       finish 
       continue 

sw('V'):
       Ecce (thisfile)
       continue 

sw('X'):
       n1 = get integer
       if  n1 <0 start 
          printline ("Invalid integer specified")
       else 
          n1=999999 if  n1=0
          dump file (thisfile,n1)
       Finish 
       continue 
   Repeat 
end 

routine  welcome

   printline ("APM Clean   Version ".version."   Current directory :".current directory)
end 

routine  begin
   string  (63) wild,home
   integer  m = 0

   on  0,1,2,3,4,5,6,7,8,9,10,11 start 
      set directory (home) unless  event_event=9 and  event_sub=3
      stop 
   finish 

   wild = Cli Param
   home = current directory

   to Upper(wild)
   Skip Blanks (wild)

   if  Wild -> user .(":"). wild start 
      open directory
      Printstring ("No such user ".user) and  newline and  stop  if  eod = 1
      set directory (user)
   else 
      user = home
      open directory
   finish 

   wild = "**" if  wild = ""
   Get Next File

   While  Eod = 0 Cycle 
      Do a file (fsp) and  m = 1 if  matches (fsp,wild)
      Get Next File
   repeat 
   printstring ("No files matched") and  newline if  m=0
   set directory (home)
end 

Begin 
   begin
Endofprogram