// PB June 1981         Types a file with pagewaiting
// PB Sept 1981         Find terminal width/depth

Section "Typ"

GET "libhdr"
GET "bcpl.setsc"                                     //sc
GET "TERMHDR"
GET "CLIHDR"

MANIFEST $( ACT.SC.READ = 995 $)                        // :g.iohdr
MANIFEST $( defscrlines = 22; term1=26 $)

STATIC
$( ch = '*N';file = 0; ofile = 0; scrlines = defscrlines; comm = 0; machine = 0;
   In.sc = FALSE; sc.pkt=0; oinput=0; ooutput=0; user.ready=FALSE
$)

/* GLOBAL $( ch : ug; file :ug+1; .ofile :ug+2
  scrlines :ug+3; comm :ug+4; machine :ug+5; baselevel:ug+6; Exit.Addr:ug+7 $)
*/

MANIFEST
$( k.file   = 0; k.stop   = 1; k.ignore = 2; k.start  = 3; k.to     = 4
   k.Noln   = 5; k.l      = 6; k.s      = 7; k.ln     = 8; k.max    = k.ln
$)

LET START(filename, input.stream) BE
$(
   LET linelen = 80

   LET set.sc(Bool) BE
   $( In.sc := bool
      setsc(bool)
      User.ready := FALSE
      IF bool THEN qpkt(sc.pkt)
   $)

   LET tidyup() BE
   $( IF In.sc THEN set.sc(FALSE)
      pktwait := taskwait
      UNLESS file = 0 $( SELECTINPUT(file); ENDREAD() $)
      UNLESS ofile = 0 $( SELECTOUTPUT(ofile); ENDWRITE() $)
      UNLESS (comm = 0) | machine $( SELECTINPUT(comm); ENDREAD() $)
      SELECTINPUT(oinput)
      SELECTOUTPUT(ooutput)
      FINISH
   $)

   LET mypktwait() = VALOF
   $( Let pkt=taskwait()
      UNLESS pkt = Sc.pkt RESULTIS pkt
      User.ready := TRUE
   $) REPEAT

   LET tidymessage(st,a,b) BE
   $( UNLESS st = 0 $( WRITEF(st,a,b);WRITES(" in Typ*N") $)
      tidyup()
   $)

   LET rdn(v) = VALOF
   $( LET res = 0
      FOR i = 1 TO v%0 TEST '0'<= v%i <= '9' THEN res := res*10 + v%i - '0'
                        ELSE tidymessage("Range must be Integers")
      RESULTIS res
   $)

   LET rdch2() = VALOF
   $( ch := RDCH()
      IF ch = ENDSTREAMCH tidymessage(0)
      RESULTIS ch
   $)

   LET term.rdch() = VALOF
   $( LET res = ?
      UNTIL User.ready DO delay(10)
      res := sc.pkt!PKT.RES1
      User.ready := FALSE
      Qpkt(sc.pkt)
      RESULTIS res
   $)

   LET gobble(ch) = VALOF
   $( LET res = -1
      WRCH('*E')
      UNLESS ch='*N'| ch='*C'  ch := capitalch(term.rdch()) REPEATWHILE ch=' '
      IF (ch='Q') | (ch='W') | (ch=endstreamch) | (ch=term1) THEN tidymessage(0)
      IF ch = 'L' THEN scrlines := maxint
      WHILE '0'<=ch<='9' $( res := (res+1) * 10 + ch -'1'; ch := term.rdch() $)
      WRCH('*N')
      RESULTIS res
   $)

   LET line     = 1
   LET from     = 1
   LET upto     = maxint
   LET ln       = TRUE
   LET chpos    = ?
   LET screen   = ?
   LET argstring= "File/a,Stop,)/s,From=Start=(,To/k,Noln/s,*
                  *W=Width/k,P=Pagelength/k,Ln/s"
   LET mcstring = "ignore/s,Stop,)/s,From=start=(,To/k,NoLn/s,*
                  *W=Width/k,P=Pagelength/k,Ln/s"
   LET SC.pkt.  = TABLE NOTINUSE, 0, ACT.SC.READ, 0,0
   LET spvec    = VEC 15
   LET v        = VEC (80/bytesperword) + k.max

   sc.pkt       := sc.pkt.
   sc.pkt!PKT.ID:= CONSOLETASK
   oinput       := input()
   ooutput      := output()
   machine      := (filename \= 0)
   ch           := '*N'
   file         := 0
   ofile        := 0

   // See if we know the terminal info ...
   $( LET type = rootnode ! RTN.TASKTAB ! CONSOLETASK ! TCB.GBASE ! TERM.GLOBAL
      UNLESS type=0
      $( UNLESS TYPE!TERM.WIDTH=0       DO linelen  :=TYPE!TERM.WIDTH
         UNLESS TYPE!TERM.DEPTH=0       DO scrlines :=TYPE!TERM.DEPTH   -1
      $)
   $)

   comm         := machine -> input.stream, findinput("**")

   IF RDARGS(machine -> mcstring, argstring,v,linelen/BYTESPERWORD + k.max)=0
   THEN tidymessage("Bad args")
   UNLESS machine
   $( filename := v!k.file
      FOR i = 0 TO 15 DO spvec!i := filename!i
      filename := spvec
   $)
   IF (v!k.stop ~= 0) & ((v!k.stop)%1 = '(')
   $( LET start = v!k.stop
      v!k.stop := v!k.start
      v!k.start := start
      start%1   := '0'
   $)
   IF (v!k.stop ~= 0) & ((v!k.stop)%((v!k.stop)%0) = ')')
   THEN (v!k.stop)%0 := (v!k.stop)%0 - 1
   UNLESS v!k.stop  = 0 upto := rdn(v!k.stop)
   UNLESS v!k.start = 0 from := rdn(v!k.start)
   IF from > upto tidymessage("Range negative")
   ln := V!K.ln |       ((~(v!k.noln)) & (~machine) &
                         (compstring("Scan",CLI.commandname)=0))
   UNLESS v!k.l  = 0 linelen  := rdn(v!k.l)
   UNLESS v!k.s  = 0 scrlines := rdn(v!k.s)
   UNLESS v!k.to = 0
   $( ofile := FINDOUTPUT(v!k.to)
      scrlines := maxint
      IF ofile = 0 tidymessage("%S not found",v!k.to)
      SELECTOUTPUT(ofile)
   $)
   IF ln linelen := linelen - 6
   screen := scrlines - 1
   chpos := linelen
   file := FINDINPUT(filename)
   IF file = 0 tidymessage("%S not found",filename)
   SELECTINPUT(file)
   UNLESS comm=0 $( set.sc(TRUE); pktwait := mypktwait $)

   IF Ln THEN WRITEF("%S******************** File %S *********************N",
         ln->"      ","",filename)

   UNTIL from = line IF RDCH() = '*N' line := line+1

   UNTIL line > upto
   $( LET och = ch
      LET Dec(Addr) BE
      $( Let Screen = (!Addr) -1
         Let Newscreen = ?

         !Addr := Screen
         IF (Comm = 0) | ( (Screen > 0) & NOT User.ready)
         DO $( WRCH('*N'); RETURN $)
         newscreen := Gobble(screen>0 -> term.rdch(), ' ')
         !Addr := (newscreen < 0) -> Scrlines, newscreen+1
      $)
      IF testflags(1) BREAK; rdch2();
      IF (chpos <= 0) & (ch ~= '*N')
         $( dec(@screen); WRITES(ln->"+++++ ","||"); chpos:=linelen $)
      IF (och = '*N') & ln THEN WRITEF("%i5 ",line)
      IF ch = '*N' THEN dec(@screen)
      chpos := chpos-1; UNLESS ch = '*N' WRCH(ch);
      IF ch = '*N' $( chpos := linelen;line := line + 1 $)
   $)
$)


