! DATED 11 NOV 1984
!***********************************************************************
!*
!*               OPER handler for an interactive terminal
!*
!*       Copyright (C) R.D. Eager   University of Kent   MCMLXXXI
!*
!*       This version converted to IMP80 and interfaced to VVP -
!*       the Virtual Video Package - by K. Yarwood, February 1982
!*       Modified for VOLUMS local pictures - C.D.McArthur, September 1982
!*
!***********************************************************************
!
!
!***********************************************************************
!*
!*          Constants
!*
!***********************************************************************
!
constinteger  no = 0, yes = 1
constinteger  stopped = 0, running = 1;   ! Clock states
constbyteinteger  null    = x'00'
constbyteinteger  cr = x'0D'
constbyteinteger  flash = x'11'
constbyteinteger  eom = x'19'
constbyteinteger  escape  = x'1B'
!
constinteger  com seg = x'80C00000';   ! Address of Supervisor communication segment
constinteger  default refresh interval = 10;   ! Seconds
constinteger  default seconds per tick = 3
!
constinteger  elapsed int service = x'000A0000'
constinteger  single kick act = 2
!
constinteger  oper service = x'00320000'
constinteger  update log act = 7
constinteger  parse com act = 14
!
constlonginteger  int mask = x'0382000A0382000A';   ! INT: A,C,Q,W,X,Y,a,c,q,w,x,y
!
constinteger  maxlcom = 5;   ! Number of local commands
conststring (2)array  lcom(1:maxlcom) = "R","MF","M","U","ST"
!
conststring (1) snl = "
"
conststring (4) lpsv = "LPSV"
!
constinteger  first loc pic=4, last loc pic=11;  ! local pictures
!
constbyteintegerarray  screen size(0:1) = 21,24
constbyteintegerarray  initial page(0:last loc pic) = 2,0,0,0,0(8)
!
owninteger  pr linex=41;owninteger  pr liney=7
owninteger  ip linex=41;owninteger  ip liney=8
owninteger  bo linex=41;owninteger  bo liney=9
owninteger  screen lines=10
!
!
!***********************************************************************
!*
!*          Record and array formats
!*
!***********************************************************************
!
recordformat  comf(integer  ocptype,ipldev,sblks,sepgs,ndiscs,c 
         ddtaddr,gpctabsize,gpca,sfctabsize,sfca,sfck,dirsite,c 
         dcodeda,suplvn,wasklokcorrect,date0,date1,date2,c 
         time0,time1,time2,epagesize,users,cattad,dqaddr,c 
         byteinteger  nsacs,resv1,sacport1,sacport0,c 
         nocps,resv2,ocpport1,ocpport0,c 
         integer  itint,contypea,gpcconfa,fpcconfa,sfcconfa,c 
         blkaddr,dptaddr,smacs,trans,longinteger  kmon,c 
         integer  ditaddr,smacpos,supvsn,pstva,secsfrmn,secstocd,c 
         sync1dest,sync2dest,asyncdest,maxprocs,inspersec,elaphead,c 
         commsreca,storeaad,procaad,sfcctad,drumtad,tslice,sp0,sp1,c 
         sp2,sp3,sp4,sp5,sp6,sp7,sp8,c 
         lstl,lstb,pstl,pstb,hkeys,hoot,sim,clkx,clky,clkz,c 
         hbit,slaveoff,inhssr,sdr1,sdr2,sdr3,c 
         sdr4,sesr,hoffbit,s2,s3,s4,end)

record  format  tmodef(half  integer  flags, byte  integer  pads, spare, linelim, page,
    byte  integer  array  tabs(1:8), byte  integer  cr, esc, del, can, prompt, end,
    half  integer  flags2, spare2, spare3, byte  integer  screed1, screed2, screed3, screed4,
    screed5, screed6)

record  format  uinff(string  (6) user, string  (31) batchfile, integer  mark, fsys, procno,
    isuff, reason, batchid, sessiclim, scidensad, scidens, operno, aiostat, scdate, sync1dest,
    sync2dest, asyncdest, aacctrec, aicrevs, string  (15) batchiden, string  (31) basefile,
    integer  previc, integer  itaddr0, itaddr1, itaddr2, itaddr3, itaddr4, streamid, dident,
    scarcity, preemptat, string  (11) spoolrfile, integer  resunits, sesslen, priority, decks,
    drives, partclose, record  (tmodef) tmodes, integer  pslot, string  (63) itaddr,
    integer  array  fclosing(0:3), integer  clo fes, uend)

const  record (uinff) name  uinf=9<<18

recordformat  iostatf(integer  inpos,string (15) intmess)
recordformat  itf(integer  inbase,inlength,inpointer,outbase,c 
                  outlength,outpointer,outbusy,omwaiting,inttwaiting,c 
                  jnbase,jncur,jnmax,lastfree,spare5,spare6,spare7)
recordformat  parmf(integer  dest,srce,p1,p2,p3,p4,p5,p6)
recordformat  scf(byteintegerarray  header(1:8),text(1:40))
recordformat  loc pic f(string (6)owner,string (11)file,integer  fsys,c 
                        addr,screens,srce)
!
ownintegerarrayformat  tablef(0:43)
ownrecord (scf)arrayformat  scaf(1:24)
!
!
!***********************************************************************
!*
!*          Owns
!*
!***********************************************************************
!
owninteger  clock status
owninteger  my sync1 dest
owninteger  prompt service
owninteger  refresh interval
owninteger  seconds per tick
owninteger  operlog altered
ownstring (40) promptstring
ownrecord  (parmf)clockp
ownrecord (iostatf)name  iostat
ownrecord (itf)name  it
ownrecord (comf)name  com
ownintegerarray  current picture(0:1) 
ownintegerarray  current page(0:1) 
ownintegerarray  resident picture(0:3)
ownrecord (scf)array  buffs(1:24,0:1)
ownrecord (loc pic f)array  local picture(first loc pic:last loc pic)
!
!
!***********************************************************************
!*
!*          Director references
!*
!***********************************************************************
!
externalstringfnspec  derrs(integer  n)
externalroutinespec  messages(string (255) s)
externalintegerfnspec  dloweracr(integer  newacr)
externalroutinespec  dpoff(record (parmf)name  p)
externalroutinespec  dpon(record (parmf)name  p)
externalroutinespec  dtoff(record (parmf)name  p)
externalintegerfnspec  dconnect(string (6)user,string (11)file,integer  fsys,c 
                                mode,apf,integername  seg,gap)
externalintegerfnspec  ddisconnect(string (6)user,string (11)file,c 
                                   integer  fsys,destroy)
!
!
!***********************************************************************
!*
!*          Subsystem references
!*
!***********************************************************************
!
systemroutinespec  console(integer  ep,integername  start,len)
systemroutinespec  etoi(integer  ad,l)
systemstringfnspec  itos(integer  n)
systemroutinespec  move(integer  length,from,to)
externalroutinespec  prompt(string (255) s)
systemintegerfnspec  pstoi(string (63) s)
systemroutinespec  reroutecontingency(integer  ep,class,longinteger  c 
                                      mask,routine  ontrap,c 
                                      integername  flag)
systemroutinespec  signal(integer  ep,p1,p2,integername  flag)
externalintegerfnspec  uinfi(integer  entry)
systemroutinespec  uctranslate(integer  ad, len)
!
!
!**********************************************************************
!*
!*              VVP references and consts
!*
!**********************************************************************

include  "CONLIB.VVP_VVPSPECS"
include  "CONLIB.VVP_VVPFORMATS"

!***********************************************************************
!*
!*          Service routines
!*
!***********************************************************************
!
!
routine  report pic off(integer  owner,pic)
! local pic pic about to go off-screen. tell owner so that he can
! stop updating it
record (parmf)p
p_dest=owner
p_p1=pic
dpon(p)
end ;       ! report pic off
!
routine  check pic off(integer  screen)
! we are about to change screen. if it currently shows a local pic
! then report it off and maybe disconnect
integer  pic,flag
record (loc pic f)name  lpic
returnunless  0<=screen<=1
pic=current picture(screen)
if  pic>=first loc pic start 
  lpic==local picture(pic)
  lpic_screens=lpic_screens-1
  if  lpic_screens=0 start ;  ! all off
    flag=ddisconnect(lpic_owner,lpic_file,lpic_fsys,0)
    ! what if flag#0 ??
  finish 
  report pic off(lpic_srce,pic)
finish 
end ;      ! check pic off
!
routine  clear pending prompts
integer  procno
string (15) s
record  (parmf)p
!
return  if  prompt service = 0;   ! No pending prompt
procno = (prompt service >> 16) - com_sync1dest
if  procno = 1 then  s = ":" else  start 
if  procno = 3 then  s = "PROMPT OFF" else  c 
                     s = "XXX"
finish 
p_srce = 7
p_dest = prompt service
string(addr(p_p1)) = s.snl
dpon(p)
end ;   ! of CLEAR PENDING PROMPTS
!
!
routine  await clock tick
record  (parmf)p
!
cycle 
   p = 0
   dpoff(p)
   exit  if  (p_dest & x'FF') = 31
repeat 
end ;   ! of AWAIT CLOCK TICK
!
!
routine  initialise terminal
integer  aitbuffer,aiostat,ad,mode
!
console(13,aitbuffer,aiostat);   ! Get vital terminal addresses
if  aitbuffer = 0 then  start 
   vv printstring("Not an interactive terminal".snl)
   stop 
finish 
!
prompt(tostring(cr))
iostat == record(aiostat)
it == record(aitbuffer)
end ;   ! of INITIALISE TERMINAL
!
!
routine  finalise terminal

vv define triggers(-2, 0, 0)
messages("ON")

end ;   ! of FINALISE TERMINAL
!
!
routine  init resident pictures
integerarrayname  gpctab
!
gpctab == array(com_gpca,tablef)
!
resident picture(0) = gpctab(41);       ! 'L'
resident picture(1) = gpctab(42);       ! 'P'
resident picture(2) = gpctab(43) + 2048;! 'S'
resident picture(3) = gpctab(43) + 3072;! 'V'
end ;   ! of INIT RESIDENT PICTURES
!
!
routine  init local pictures
integer  i
record (loc pic f)name  lpic
for  i=first loc pic,1,last loc pic cycle 
  lpic==local picture(i)
  lpic=0
  lpic_owner="VOLUMS"
repeat 
end ;         ! init local pictures
!
!
routine  init picture buffers
integer  screen,line
byteintegerarrayname  hd
record (scf)arrayname  buff
!
cycle  screen = 0,1,1
   buff == array(addr(buffs(1,screen)_header(1)),scaf)
   cycle  line = 1,1,24
      hd == buff(line)_header
      hd(1) = escape
      hd(2) = 'X'
      hd(3) = 0 {line address char(line)}
      hd(4) = escape
      hd(5) = 'Y'
      hd(6) = (1-screen)*41  {screen address char(screen)}
      hd(7) = null
      hd(8) = null
   repeat 
   current picture(screen) = -1
   current page(screen) = -1
repeat 
end ;   ! of INIT PICTURE BUFFERS
!
!
routine  transfer line(string (40) s)

   vv goto(bo linex, bo liney)
   vv printstring(s)
   vv print ch(clr rol char)

   vv goto(ip linex, ip liney)
   vv printch(clr rol char)

end ;   ! of TRANSFER LINE
!
!
routine  update operlog(string (23) s)
record  (parmf)p
!
p_dest = oper service!update log act
p_srce = 0
string(addr(p_p1)) = s
dpon(p)
operlog altered = yes
end ;   ! of UPDATE OPERLOG
!
!
routine  oper message(string (40) mes,integer  doflash)
integer  l,max
string (23) s
!
if  doflash = yes then  max = 22 else  max = 23
cycle 
   s <- mes
   if  flash = yes then  charno(s,23) = flash
   update operlog(s)
   l = length(mes) - max
   exit  unless  l > 0
   length(mes) = l
   move(l,addr(mes)+max+1,addr(mes)+1)
repeat 
end ;   ! of OPER MESSAGE
!
!
routine  local command(string (40) s)
integer  i,doflash
string (40) comm,param
switch  csw(1:maxlcom)
!
return  if  length(s) <= 1
s = substring(s,2,length(s))
!
s = substring(s, 2, length(s)) while  length(s)>1 and  charno(s,1)=' '
s = s." ".comm while  s -> s.("  ").comm
unless  s -> comm.(" ").param then  start 
   comm = s
   param = ""
finish 
!
cycle  i = 1,1,maxlcom
   if  comm = lcom(i) then  -> csw(i)
repeat 
transfer line("** Illegal local command")
return 
!
csw(1):   ! (R)efresh rate
   if  param = "" then  start 
      refresh interval = default refresh interval
   finish  else  start 
      i = pstoi(param)
      if  5 <= i <= 600 then  start 
         refresh interval = i
         transfer line("** OK")
      finish  else  transfer line("** Invalid value")
   finish 
   return 
   !
csw(2):   ! (M)essage to OPERLOG and (F)lash
   doflash = yes
   -> csw3a
   !
csw(3):   ! (M)essage to OPERLOG
   doflash = no
csw3a:
   oper message(param,doflash)
   transfer line("** Message sent")
   return 
   !
csw(4):   ! (U)sers - number of
   i = com_users - 3
   i = 1 if  i < 1
   param = "** ".itos(i)." User"
   if  i > 1 then  param = param."s"
   transfer line(param)
   return 
   !
csw(5):   ! (S)econds per (T)ick
   if  param = "" then  start 
      seconds per tick = default seconds per tick
   finish  else  start 
      i = pstoi(param)
      if  2 <= i <= 20 then  start 
         seconds per tick = i
         transfer line("** OK")
      finish  else  transfer line("** Invalid value")
   finish 
   clockp_p2 = seconds per tick
   return 
   !
end ;   ! of LOCAL COMMAND
!
!
routine  ontrap(integer  class,subclass)
integer  flag
!
console(7,flag,flag);   ! Kill output
check pic off(flag) for  flag=0,1,1;   ! local pics ?
clear pending prompts
finalise terminal
if  clock status = running then  await clock tick
signal(3,class,subclass,flag);   ! Get the Subsystem to do the rest
end ;   ! of ONTRAP
!
!
routine  set prompt(string (15) s,integer  srce)
promptstring <- s
if  srce # 0 then  start 
   srce = srce >> 16
   promptstring <- promptstring." from ".itos(srce-com_sync1dest)
finish 
end ;   ! of SET PROMPT
!
!
routine  display prompt

   vv goto(pr linex, pr liney)
   vv printstring(promptstring)
   vv printch(clr rol char)
   vv goto(pr linex, pr liney + 1)
   vv printch(clr rol char)

end ;   ! of DISPLAY PROMPT
!
!
routine  display picture(integer  screen,picture,reqpage)
integer  picad,size,ad,len,i,picmax,picsize,page,j
record (scf)arrayname  buff
!
return  unless  0 <= picture <= last loc pic and  0 <= screen <= 1
if  picture<first loc pic then  picad = resident picture(picture) c 
                          else  picad=local picture(picture)_addr
return  if  picad = 0
page = reqpage
if  page = -1 then  page = initial page(picture)
!
len = integer(picad)
size = screen size(screen)
picsize = size*41
!
buff == array(addr(buffs(1,screen)_header(1)),scaf)
picad = picad + 8
picmax = picad + len
picad = picad + picsize*page
while  picad > picmax cycle ;           ! the picture may have shrunk
  picad = picad - picsize;              ! by several pages since we were here
  page = page - 1;                      ! last, so get back into last page
repeat 
if  picad + picsize > picmax  and  page > 0 then  picad = picmax - picsize
! we cant back up if the short last page is also the first page. we have to
! assume that there is at least one page addressable regardless of len.
!
if  current picture(screen) = picture and  c 
    current page(screen) = page and  c 
    reqpage >= 0 then  return 
current picture(screen) = picture
current page(screen) = page
!
size=screen lines if  screen lines<size
cycle  i = 1,1,size
   ad = addr(buff(i)_text(1))
   move(40,picad,ad)
   etoi(ad,40) if  picture<first loc pic;    ! local pictures are ISO

   ! Output to VVP
   vv goto(buff(i)_header(6), i-1)
   for  j=1,1,40 cycle 
      vv print ch(buff(i)_text(j))
   repeat 

   picad = picad + 41
repeat 

end ;   ! of DISPLAY PICTURE
!
!
routine  display new page(integer  screen,change)
integer  newpage
!
return  unless  0 <= screen <= 1
newpage = current page(screen) + change
if  newpage < 0 then  newpage = 0
display picture(screen,current picture(screen),newpage)
end ;   ! of DISPLAY NEW PAGE
!
!
routine  readline(stringname  s)
   s=""
   vv rstrg(s)
   uctranslate(addr(s)+1, length(s))

end ;   ! of READLINE
!
!
integerfn  same(integer  ad1,ad2)
*ldtb  _x'18000028';   ! Byte descriptor, bound 40
*lda   _ad1;           ! Form desc to first string
*cyd   _0;             ! Copy to ACC for compare
*lda   _ad2;           ! Form desc to second string
*cps   _l =dr ;        ! Compare them
*jcc   _8,<equal>;     ! Jump if they are the same
result  = no
!
equal:
result  = yes
end ;   ! of SAME
!
!
routine  update picture(integer  picture)
integer  screen,picad,picmax,size,i,len,page,ad,copyad,picbase,picsize,j
integer  from,to,step,adinc,uad,ch{copy2ad
byteintegerarray  p2copy(1:40)
byteintegerarray  pcopy(1:24*41)
record (scf)arrayname  buff
!
return  unless  0 <= picture <= last loc pic
if  picture<first loc pic then  picbase = resident picture(picture) c 
                          else  picbase=local picture(picture)_addr
return  if  picbase = 0
len = integer(picbase)
picbase = picbase + 8
picmax = picbase + len
{opy2ad = addr(p2copy(1))
!
cycle  screen = 0,1,1
   continue  unless  current picture(screen) = picture
   size = screen size(screen)
   picsize = size*41
   buff == array(addr(buffs(1,screen)_header(1)),scaf)
   page = current page(screen)
   picad = picbase + picsize*page
   while  picad > picmax cycle 
     picad = picad - picsize
     page = page -1
   repeat 
   current page(screen) = page
   if  picad + picsize > picmax and  page > 0 then  picad = picmax - picsize
   copyad = addr(pcopy(1))          {address for local copy of current state}
   move(picsize,picad,copyad)       {take copy of whole of resident picture}
   etoi(copyad,picsize) if  picture<first loc pic
   !
   if  picture = 0 then  start 
      from = size
      to = 1
      if  screen lines<size then  from=screen lines-3
      step = -1
      adinc = -41
      copyad = copyad + (size - 1)*41
   finish  else  start 
      from = 1
      to = size
      if  screen lines<to then  to=screen lines
      step = 1
      adinc = 41
   finish 

   cycle  i = from,step,to
      ad = addr(buff(i)_text(1))     {address of program's copy of screen}
      if  same(copyad,ad) = no then  start 
         move(40, copyad, ad)        {move current value to program's copy}

         ! Send to VVP

         vv goto(buff(i)_header(6), i-1)
         for  j=1,1,40 cycle 
            vv print ch(buff(i)_text(j))
         repeat 

      finish 
      copyad = copyad + adinc
   repeat 

repeat 
end ;   ! of UPDATE PICTURE
!
!
!***********************************************************************
!*
!*          O P E R
!*
!***********************************************************************
!
externalroutine  oper(string (255) parms)
integer  flag,done useful work,dact,l,refresh counter,screen,seg,gap,pic
integer  new prompt service
string (31) work1,work2
string (40) line
record  (parmf)p
record (loc pic f)name  lpic
record (boxf)name  box
record (subscrf) screenrec
record (subscrf) name  scr
switch  act(0:31)

routine  otx
printstring("
");printstring("Screen operations are currently not possible on PAD connections to EMAS.
");printstring("Development of the JNT-sponsored screen protocol SSMP is awaited (November 1984)
");printstring("Perhaps your conversion to a PAD port was premature.
");
end  {otx}
messages("OFF")
if  parms="" start 
   work1<-string(uinf_itaddr)
   flag=1 {set to zero if any non-numeric found in ITADDR}
   for  l=1, 1,length(work) cycle 
      unless  '0'<=charno(work, l)<='9' then  flag=0
   repeat 
   if  flag=0 start 
      otx
      return 
   finish 

   vv init(l)
   if  l#0 start     {failure to init }
      printstring("Cannot run OPER on this terminal type")
      newline
      return 
   finish 
   vv define triggers(3, 0, 0)     {allow left-right cursor movement only}
finish {%else %start
   scr==record(vv screen descriptor address)
   screenrec=scr
   box==screenrec_box
   pr linex=box_wid-24;   bo liney=box_dep-1
   pr linex=41 if  pr linex>41
   ip linex=pr linex  ;   ip liney=bo liney-1
   bo linex=pr linex  ;   pr liney=ip liney-1
   screen lines=box_dep
!finish
clock status = stopped
com == record(com seg)
my sync1 dest = uinfi(7)
prompt service = 0
refresh counter = 0
refresh interval = default refresh interval
seconds per tick = default seconds per tick
operlog altered = no
flag = dloweracr(2);   ! Raise privilege
reroutecontingency(3,65,int mask,ontrap,flag);   ! Catch INT: messages
initialise terminal
init picture buffers

init resident pictures
init local pictures
display picture(1,1,-1);   ! Display process list on screen 1
display picture(0,0,-1);   ! Display OPER log on screen 0
set prompt("COMMAND:",0)
display prompt
clockp_srce = 0
clockp_dest = elapsed int service!single kick act
clockp_p1 = my sync1 dest!31;   ! My activity number for reply
clockp_p2 = seconds per tick
vv update screen
dpon(clockp);   ! Request initial clock tick
clock status = running

cycle 
   done useful work = no
   if  iostat_inpos # it_inpointer then  start     {There is some input}
      readline(line)
      if  length(line) # 0 or  prompt service # 0 then  start 
         exit  if  line = ".END" or  line = "*" or  line = "Q" or  c 
         line="QUIT" or  line="STOP" or  line="END" or  line="FINISH" or  c 
         line="LOG" or  line="LOGOFF"
         done useful work = yes
         if  charno(line,1) = '!' then  start 
            local command(line)
            continue 
         finish 
         if  length(line) > 23 then  length(line) = 23
         transfer line(line)
         new prompt service = 0
         if  prompt service = 0 then  start 
            p_dest = oper service!parse com act
         finish  else  start 
            p_dest = prompt service
            update operlog(line)
            l = length(line)
            if  l # 0 and  charno(line,l) = '&' then  start 
               charno(line,l) = ' '
               set prompt("CONTINUE:",prompt service)
               new prompt service = prompt service
            finish  else  start 
               if  l > 22 then  l = 22
               charno(line,l + 1) = nl
               length(line) = l + 1
               set prompt("COMMAND:",0)
            finish 
            display prompt
         finish 
         p_srce = 7
         string(addr(p_p1)) = line
         dpon(p)
         prompt service = new prompt service    {Done after PON in case of interruption}
      finish  else  display prompt
   finish 
   p_dest = 0
   dtoff(p)
   if  p_dest = 0 and  done useful work = no then  vv update screen and  dpoff(p)
   dact = p_dest & x'FF';   ! May be zero if the TOFF didn't find anything
   !
   -> act(dact)
   !
act(0):    ! Null action
   continue 
   !
act(31):   ! Clock tick
   clock status = stopped
   refresh counter = refresh counter + seconds per tick
   if  refresh counter >= refresh interval then  start 
      refresh counter = 0
      cycle  screen = 0,1,1
         update picture(current picture(screen))
      repeat 
      display prompt
   finish  else  start 
      if  operlog altered = yes then  start 
         update picture(0)
         display prompt
      finish 
   finish 

   dpon(clockp);   ! Request fresh clock tick
   clock status = running
   continue 
   !
act(1):    ! Output string
act(7):    ! String to OPER log
   update operlog(string(addr(p_p1)))
   continue 
   !
act(6):         ! display a local picture
   ! p1=picture number, p2=fsys for file, p3=screen, p4,5,6=filename
   unless  0<=p_p3<=1 start ;   ! screen out of bounds
     report pic off(p_srce,p_p1);  ! owner will have incremented refresh count
     continue 
   finish 
   pic=current picture(p_p3);   ! whats showing
   if  pic=p_p1 start ;     ! already there
     report pic off(p_srce,p_p1);  ! as above
     continue 
   finish 
   ! so a new picture about to go on screen p_p3
   check pic off(p_p3);   ! it may be a local
   ! now the new one
   lpic==local picture(p_p1)
   if  lpic_screens=0 start ;  ! not currently showing. so connect it
     lpic_file=string(addr(p_p4))
     lpic_fsys=p_p2
     seg=0
     gap=0
     flag=dconnect(lpic_owner,lpic_file,lpic_fsys,9,0,seg,gap)
     if  flag#0 start 
      transfer line(derrs(flag))
      continue 
    finish 
     lpic_addr=seg<<18+24;    ! where the length is
     lpic_screens=1
     lpic_srce=p_srce
   finishelse  lpic_screens=lpic_screens+1
   display picture(p_p3,p_p1,-1)
   display prompt
   continue 
   !
act(19):   ! Request for picture change
   if  p_p1 < 0 then  start ;   ! Translate symbolic picture name
      if  lpsv -> work1.(string(addr(p_p3))).work2 then  start 
         p_p1 = length(work1)
      finish 
   finish 
   if  p_p1>=first loc pic thencontinue ;  ! not this way
   check pic off(p_p2);   ! may be a local pic about to go off
   display picture(p_p2,p_p1,-1)
   display prompt
   continue 
   !
act(18):   ! Request for page change
   display new page(p_p2,p_p1)
   display prompt
   continue 
   !
act(8):    ! Prompt
   prompt service = p_srce
   set prompt(string(addr(p_p1)),prompt service)
   display prompt
   continue 
repeat 
!
check pic off(flag) for  flag=0,1,1
clear pending prompts
finalise terminal if  parms=""
if  clock status = running then  await clock tick
end ;   ! of OPER
endoffile