external  routine  spec  call(string  (31) cmd, string  (255) par)
external  routine  spec  prompt(string  (255) s)
external  routine  spec  list(string  (255) s)
external  routine  spec  nrstrg(string  name  s)
external  string  fn  spec  ucstring(string  (255) s)
system  string  fn  spec  itos(integer  i)

system  integer  fn  spec  current packed dt
system  integer  fn  spec  pack date and time(string  (8) date, time)
system  string  fn  spec  unpack date(integer  i)
system  string  fn  spec  unpack time(integer  i)

external  routine  spec  read profile(string  (11) key, name  info, integer  name  version, uflag)
external  routine  spec  write profile(string  (11) key, name  info, integer  name  version, uflag)


const  integer  max profile entries=10
const  string  (7) browse file="T#DOCX", docfile="T#DOC"

const  integer  yes=1, no=0
const  string  (9) unused="Unused", deleted="Deleted", completed="Completed",
   after="After", null="Null", current="Queued",
   running="Running", sending="Sending"

external  routine  spec  documents(string  (255) s)
external  routine  spec  despace(string  name  s)
external  integer  fn  spec  outpos
external  routine  spec  define(string  (255) s)
external  routine  spec  clear(string  (255) s)
external  routine  spec  rstrg(string  name  s)
external  integer  fn  spec  bin(string  (255) s)



external  routine  browsedocs(string  (255) s)

record  format  docf(integer  dtword, string  (15) file, string  (7) docno, queue,
    string  (9) state)
record  format  drf(integer  max, point, n, string  (31) editor,
    record  (docf) array  doc(1:max profile entries))

routine  spec  brhelp
routine  spec  print entry(record  (docf) r)
routine  spec  get doc info
routine  spec  sort2(record  (docf) array  name  p, integer  array  name  x, integer  num)

integer  vsn, flag, j, point, max, k, no of cur docs, inserted, updated, hit
integer  do documents, do display, ch, dtw
record  (drf) r, tempr
record  (docf) name  ss
string  (9) new state, queue, date1, time1
string  (31) editor
string  (127) a, b, file, docno
integer  array  x(1:max profile entries)

const  integer  max new docs=20
record  (docf) array  curdocs(1:max new docs)

   on  event  9 start 
      ->eof
   finish 

   vsn=1
   max=max profile entries
   editor="LIST"
   updated=no

   ! Get profile information
   read profile("Docs", r, vsn, flag)
   if  flag=2 {profile entry wrong size} or  flag=3 {profile not exist} or  c 
      flag=4 {keyword not found} start 
      ! Initialise profile array
      r=0
      r_max=max; r_point=1; r_editor=editor
      for  j=1, 1, max cycle 
         r_doc(j)_state=unused
      repeat 
      updated=yes
      if  flag=2 then  vsn=-1 {delete existing entry}
   finish  else  if  flag=0 start 
      max=r_max
      editor=r_editor
   finish  else  start 
      printstring("Read profile fails"); write(flag, 1)
      newline
      return  {bad failure}
   finish 

   do documents=yes
   do display=no

   ! Analyse parameters
   if  s="?" start 
      brhelp
      return 
   finish  else  if  s="*" start 
      newline
      printstring("Give maximum number of entries to be held (max ".itos(max profile entries). c 
         ", currently ".itos(max))
      printstring(")
or CR to leave unchanged")
      newlines(2)
      prompt("No of entries: ")
      cycle 
         nrstrg(s)
         if  s="" then  exit 
         j=bin(s)
         if  0<j<=max profile entries start 
            if  j#max then  vsn=-1
            {different from existing value, so delete profile entry and make new}
            r_max=j
            updated=yes
            exit 
         finish 
      repeat 
      printstring("Give entry point name to be used for displaying Documents")
      printstring(" (currently ".r_editor.")
or CR to leave unchanged")
      newlines(2)
      prompt("Entry point: ")
      cycle 
         nrstrg(s)
         s=ucstring(s)
         if  length(s)<=31 start 
            if  s#"" start 
               r_editor=s
               editor=s
               updated=yes
            finish 
            exit 
         finish 
      repeat 
   finish  else  if  s="LIST" or  s="SHOW" or  s="LOOK" start 
      editor=s
      do documents=no
      do display=yes
   finish  else  if  s#"" start 
      hit=0 {set one if non-alpha-num found}
      for  j=1, 1, length(s) cycle 
         ch=charno(s, j)
         unless  'A'<=ch<='Z' or  '0'<=ch<='9' then  hit=1
      repeat 
      if  hit=0 start 
         editor=s
         do display=yes
      finish  else  start 
         printstring("Invalid parameter")
         newline
         return 
      finish 
   finish 

   no of cur docs=0
   if  do documents=yes start 
      printstring("Documents()"); newline
      define("9,".docfile)
      select output(9)
      documents("")
      select output(0)
      close stream(9)
      select input(9)
      no of cur docs=0
      cycle 
         rstrg(s)
         if  s->a.("Queue").b and  a="" start 
            despace(b)
            queue=b
         finish 

         if  length(s)>47 start 
            docno=substring(s, 25, 29) {doc ident position}
            despace(docno)
            j=bin(docno)
            if  0<j<=9999 start 
               ! Assume decent document number
               no of cur docs=no of cur docs+1
               if  no of cur docs>max new docs start 
                  printstring("Too many new documents!!")
                  newline
                  return 
               finish 

               file=substring(s, 1, 15); despace(file)
               date1=substring(s, 31, 38)
               time1=substring(s, 40, 47)

               curdocs(no of cur docs)_docno=docno
               curdocs(no of cur docs)_dtword=pack date and time(date1, time1)
               curdocs(no of cur docs)_queue=queue
               curdocs(no of cur docs)_file=file
               curdocs(no of cur docs)_state=current
               ! print entry(curdocs(no of cur docs))
            finish 
         finish 
      repeat 
eof:
      select input(0)
      close stream(9)
      clear("9")
      list(docfile)
   finish  {do documents=yes}

   !----------------------------------------------------------------------------
   ! R is now set up.
   point=r_point
   for  k=1, 1, no of cur docs cycle 
      inserted=no
      hit=0
      j=point
      cycle 
         ss==r_doc(j)
         if  ss_docno=curdocs(k)_docno then  hit=1
         j=j+1; j=1 if  j>max
      repeat  until  j=point

      if  hit#0 then  continue 

      ! Then new, so insert
      cycle 
         ss==r_doc(j)
         if  ss_state=unused start 
            ss=curdocs(k)
            r_n=r_n+1 if  r_n<max
            inserted=yes
            updated=yes
            exit 
         finish 
         j=j+1; j=1 if  j>max
      repeat  until  j=point

      if  inserted=no start 
         ! Array is full. Use oldest entry. Point points to the oldest.
         ! "Point+1", "Point+2", ... get newer and newer. "Point-1" is newest
         r_doc(point)=curdocs(k)
         point=point+1
         point=1 if  point>max
         r_n=r_n+1 if  r_n<max
         updated=yes
      finish 
   repeat 

   !----------------------------------------------------------------------------
   ! Now look for profile entries which are Queued, but no longer "current"
   define("10,".browse file)
   j=point
   cycle 
      hit=0
      ss==r_doc(j)
      if  ss_state=after then  dtw=ss_dtword else  dtw=0
      if  ss_state=current or  ss_state=running or  ss_state=sending or  c 
         dtw<<1>>1>=current packed dt<<1>>1 start 
         for  k=1, 1, no of cur docs cycle 
            if  curdocs(k)_docno=ss_docno then  hit=1
         repeat 
         if  hit=0 and  do documents=yes start 
            printstring("Documents(".ss_docno.")"); newline
            get doc info
            if  new state#null start 
               ss_state=new state
               ss_dtword=pack date and time(date1, time1)
               updated=yes
            finish  else  printstring("? Not Deleted/Completed?") and  newline
         finish 
      finish 
      j=j+1; j=1 if  j>max
   repeat  until  j=point

   ! Sort entries on dtword
   sort2(r_doc, x, r_n)
   tempr=r
   hit=no {Array altered by sort?}
   for  j=1, 1, r_n cycle 
      if  x(j)#j then  hit=yes
      r_doc(j)=tempr_doc(x(j))
   repeat 
   point=1 {always, now}
   if  hit=yes then  updated=yes

   ! Update the PROFILE file
   if  updated=yes start 
      r_point=point
      cycle 
         write profile("Docs", r, vsn, flag)
         if  flag#0 start 
            printstring("Write profile flag"); write(flag, 1)
            newline
         finish 
         exit  if  vsn>0
         vsn=1
      repeat 
   finish 

   return  if  do display=no
   ! Now report all entries.
   printstring("Recorded status")
   printstring(" [Max entries:"); write(max, 1)
   printstring("  No used:"); write(r_n, 1)
   printstring("]")
   newline
   if  do display=yes then  select output(10)
   j=point
   cycle 
      ss==r_doc(j)
      print entry(ss) if  ss_state#unused
      j=j+1; j=1 if  j>max
   repeat  until  j=point
   if  do display=yes start 
      select output(0)
      close stream(10)
   finish 
   clear("10")

   if  do display=yes then  call(editor, browse file)

!----------------------------------end body-------------------------------------
string  fn  day of week(integer  dtword)
const  string  (3) array  ww(0:6)="Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"
integer  day
   day=dtword<<1>>1
   day=day//86400 {days since 1st Jan 1970}
   day=day-(day//7)*7 {day in week}
   result =ww(day)
end  {day of week}

routine  print entry(record  (docf) tt)

const  integer  dtab=16,      {tab for docno}
              qtab=dtab+4,    {tab for queuename}
              stab=qtab+8,    {tab for state}
              ntab=stab+11,   {tab for dayname}
              ttab=ntab+4,    {tab for date}
              itab=ttab+9     {tab for time}

string  (8) date, time, dayname

   date=unpack date(tt_dtword)
   time=unpack time(tt_dtword)
   dayname=day of week(tt_dtword)
   printstring(tt_file); spaces(dtab-outpos)
   printstring(tt_docno); spaces(qtab-outpos)
   printstring(tt_queue); spaces(stab-outpos)
   printstring(tt_state)
   spaces(ntab-outpos); printstring(dayname)
   spaces(ttab-outpos); printstring(date)
   spaces(itab-outpos); printstring(time)
   newline
end  {print entry}

!-------------------------------------------------------------------------------
routine  get doc info
string  (255) s, aa, bb, cc, after found
   on  event  9 start 
      ->eof2
   finish 
   select output(10)
   documents(ss_docno)
   select output(0)
   close stream(10)
   select input(10)
   new state=null
   after found=null
   cycle 
      rstrg(s)
      !printstring("++".s)
      !newline
      if  s->aa.("Completed at ").bb then  new state=completed else  if  c 
         s->aa.("Deleted at ").bb then  new state=deleted
      if  s->aa.("after=").cc then  after found=after
   repeat 
eof2:
   cycle 
      if  new state#null start 
         date1=substring(bb, 1, 8)
         time1=substring(bb, 10, 17)
      finish 
      if  after found=null then  exit  else  if  c 
         new state#completed and  new state#deleted and  new state#running start 
         after found=null
         new state=after
         bb=cc
      finish  else  exit 
   repeat 
   select input(0)
   close stream(10)
end  {get doc info}
routine  brhelp
   printstring("BROWSEDOCS is used to record and display a history of documents submitted to the
")
   printstring("Spooling system. It can LIST or SHOW or LOOK at the stored history. The
")
   printstring("following table gives the various actions.
"); printstring("
"); printstring("Parameter           Calls DOCUMENTS?    Inspects stored     Using command:
")
   printstring("                                        history?
"); printstring("
"); printstring("none(null)          Yes                 Yes                 stored in PROFILE
")
   printstring("
"); printstring("DOC                 Yes                 No                  -
")
   printstring("
"); printstring("LIST,SHOW,LOOK      No                  Yes                 LIST,SHOW,LOOK
")
   printstring("
"); printstring("Other alphnumeric   No                  Yes                 parameter given
")
   printstring("
"); printstring("*                   Yes                 Yes                 stored in PROFILE.
")
   printstring("
"); printstring("Additionally, ""*"" allows the default max no(10) of stored entries and the
")
   printstring("default display command(LIST) to be altered.
"); printstring("
"); printstring("The action will usually be quicker if DOCUMENTS is not called, but it's
")
   printstring("necessary to have DOCUMENTS called once while a document is queued (e.g.
")
   printstring("immediately after a LIST or DETACH command) in order to get its details
")
   printstring("recorded.
");
end  {brhelp}

routine  sort2(record  (docf) array  name  p, integer  array  name  x, integer  num)
! DECLARE INTEGER ARRAY X, BOUNDS 1:NUM, IN CALLING ROUTINE
integer  i, j, hit, n
   cycle  i=1, 1, num
      x(i)=i
   repeat 
   cycle  i=num-1, -1, 1
      hit=0
      cycle  n=1, 1, i
         if  p(x(n))_dtword<<1>>1>p(x(n+1))_dtword<<1>>1 start 
            j=x(n)
            x(n)=x(n+1)
            x(n+1)=j
            hit=1
         finish 
      repeat 
      if  hit=0 then  exit 
   repeat 
end  {sort2}

end  {browsedocs}

end  of  file