LineEDitor
From Pickwiki
Back to BasicSource
My version of Unidata's AE that was written to cope with a move to Universe when we were relying on AE's security capabilities. This has a few extra things like an embedded full-page editor and search and change histories. The original source code (version 1.03) was released to public domain by Public Trust of New Zealand as a way of thanking the Pick community for assistance given over the years.
https://sites.google.com/site/nzpickie/home/programs
program led
* This editor reproduces the UniData Alternate Editor for QM/U2
* The code is based on LED, a line editor released into
* the public domain by Public Trust of New Zealand.
* Written by Keith Robert Johnson.
*====================================================================
* Version information
* 2.00 - Simplified code - No longer supporting R83
* Downcased the source to comply with QM standards.
*====================================================================
$define universe
$ifdef qm
$include err.h
voc = @voc
$else
open 'VOC' to voc else stop 201,'VOC'
$endif
$ifdef universe
$options information
$endif
$ifdef unidata
$basictype 'U'
$endif
* INITIALISE
prompt ''
am = char(254); vm = char(253); sm = char(252)
true = 1 = 1; false = not(true); qt = '"\':"'"
common /led$data/ edkeep,secure,kept
equ cellsize to 100
dim memr(1)
* List of verbs for viewing data only
viewverb = 'VIEW':am:'BROWSE':am:'LOOK'
* XCOM data - YES this editor will do $commands like AE does
dim junk(100)
equ this to junk(1)
equ item to junk(2)
equ here to junk(3)
equ x$cc to junk(11)
equ comi to junk(13)
equ comd to junk(14)
equ last to junk(15)
equ comdmark to junk(19)
equ wordmark to junk(20)
equ fnam to junk(24)
equ xsep to junk(25)
mat junk = ''
xsep = ' '
wordmark = ' '
comdmark = '`'
* Local data
begn = @(0) ; ceop = @(-3) ; ceol = @(-4) ; goup = @(-10)
revb = @(-13) ; revf = @(-14) ; undb = @(-15) ; undf = @(-16)
heap = false ; salt = '' ; rlen = 0
plen = system(3)-1 ; pwin = plen-1 ; line = '' ; here = 0
dim fr(10) ; mat fr = '' ; fr(3) = 'MCU'
oops = '' ; oopc = '' ; oopl = '' ; oopf = ''
oopb = '' ; oopk = ''
join = '' ; nill = '' ; fold = ''
macn = 0 ; macc = ''
pick = '' ; lastfind = '' ; huge = 99999999
* Turn off page prompt
test = @(0,0)
* Find Match words - a LOOP can have multiple WHILE and UNTIL conditions
fm.words = '' ; fm.findf = '' ; fm.finda = ''
fm.words<1> = 'END' ; fm.findf<1> = 'END'
fm.finda<1> = 'IF':vm:'END':vm:'OPEN':vm:'OPENSEQ':vm:'BEGIN':vm:'LOCATE'
fm.words<2> = 'LOOP' ; fm.findf<2> = 'REPEAT':vm:'UNTIL':vm:'WHILE'
fm.words<3> = 'UNTIL'; fm.findf<3> = fm.findf<2>
fm.finda<3> = 'LOOP':vm:'UNTIL':vm:'WHILE'
fm.words<4> = 'WHILE'
fm.findf<4> = fm.findf<2>; fm.finda<4> = fm.finda<3>
fm.words<5> = 'FOR' ; fm.findf<5> = 'NEXT'
fm.words<6> = 'NEXT' ; fm.finda<6> = 'FOR'
fm.words<7> = 'BEGIN' ; fm.findf<7> = 'END CASE':vm:'CASE'
fm.words<8> = 'CASE' ; fm.findf<8> = 'CASE':vm:'END CASE'
fm.finda<8> = 'BEGIN CASE':vm:'CASE'
fm.words<9> = 'LOCKED' ; fm.findf<9> = 'END'
fm.finda<9> = 'READU':vm:'READVU':vm:'MATREADU'
fm.words<10> = 'REPEAT' ; fm.finda<10> = fm.finda<3>
* Special for C code
fm.words<11> = '{' ; fm.findf<11> = '}'
fm.words<12> = '}' ; fm.finda<12> = '{'
*
endwords = 'IF\OPEN\OPENSEQ\READNEXT\READ\READU\READV\READVU\'
endwords := 'MATREAD\MATREADU\LOCATE'
convert '\' to am in endwords
* page editor stuff
botl = system(3) - 2; clpg = @(-1)
* bell = char(7) ; span = system(2)
bell = @sys.bell ; span = system(2)
bott = @(0,system(3)-1):ceol
* Define key activity numbers - 22 keys defined
equ uarr to 1, darr to 2, larr to 3, rarr to 4
equ upag to 5, dpag to 6, lpag to 7, rpag to 8
equ tpag to 9, bpag to 10
equ escp to 11, phlp to 12, zoom to 13
equ delc to 14, dell to 15, delr to 16
equ back to 17, carr to 18, togg to 19, writ to 20
equ skey to 21, rkey to 22
* Set up the keys - In QM we can use generic key mapping (YAY)
* but I also like to have default keys
acts = '' ; keys = ''
* Arrow keys
acts<-1> = uarr ; keys<-1> = char(205)
acts<-1> = uarr ; keys<-1> = char(26)
acts<-1> = darr ; keys<-1> = char(206)
acts<-1> = darr ; keys<-1> = char(10)
acts<-1> = larr ; keys<-1> = char(203)
acts<-1> = larr ; keys<-1> = char(21)
acts<-1> = rarr ; keys<-1> = char(204)
acts<-1> = rarr ; keys<-1> = char(6)
* Page movement keys
acts<-1> = upag ; keys<-1> = char(207)
acts<-1> = upag ; keys<-1> = char(16)
acts<-1> = dpag ; keys<-1> = char(208)
acts<-1> = dpag ; keys<-1> = char(14)
acts<-1> = lpag ; keys<-1> = char(209)
acts<-1> = lpag ; keys<-1> = char(1)
acts<-1> = rpag ; keys<-1> = char(210)
acts<-1> = rpag ; keys<-1> = char(5)
acts<-1> = tpag ; keys<-1> = char(214)
acts<-1> = tpag ; keys<-1> = char(20)
acts<-1> = bpag ; keys<-1> = char(215)
acts<-1> = bpag ; keys<-1> = char(2)
* delete character, line, and delete to end of line keys
acts<-1> = delc ; keys<-1> = char(212)
acts<-1> = delc ; keys<-1> = char(4)
acts<-1> = dell ; keys<-1> = char(216)
acts<-1> = dell ; keys<-1> = char(127)
acts<-1> = dell ; keys<-1> = char(24)
acts<-1> = delr ; keys<-1> = char(217)
acts<-1> = delr ; keys<-1> = char(11)
acts<-1> = delr ; keys<-1> = char(18) ;* for Wyse terminals
* backspace and carriage return keys
acts<-1> = back ; keys<-1> = char(008)
acts<-1> = carr ; keys<-1> = char(013)
* escape, help, Go to line, toggle insert/overwrite mode, save keys
acts<-1> = escp ; keys<-1> = char(027)
acts<-1> = escp ; keys<-1> = char(017)
acts<-1> = phlp ; keys<-1> = char(128)
acts<-1> = zoom ; keys<-1> = char(007)
acts<-1> = togg ; keys<-1> = char(211)
acts<-1> = togg ; keys<-1> = char(009)
acts<-1> = writ ; keys<-1> = char(129)
acts<-1> = writ ; keys<-1> = char(023)
* search key, reverse search key
acts<-1> = skey ; keys<-1> = char(130) ;* F3 for search
acts<-1> = rkey ; keys<-1> = char(166) ;* shift-F3 for reverse search
mode = 'LINE'
* The saved stuff
pres = '' ; look = '' ; stak = ''
wild = false ; shew = false
chan = '' ; olda = '' ; cmat = '' ; mmat = ''
caseflag = false ; spaceflag = true ; blockflag = true
* Save the standard defaults in the session variable if it's not set
$ifdef universe
if unassigned(edkeep) then edkeep = '0'
$else
if assigned(edkeep) else edkeep = '0'
$endif
if edkeep eq '0' then
edkeep = pres:am:look:am:stak:am:wild:am:chan:am:olda:am:shew
edkeep := am:cmat:am:mmat:am:not(caseflag):am:not(spaceflag)
edkeep := am:not(blockflag)
kept = ''
end
* Get the 'as-is' settings from the session variable
pres = edkeep<1>
look = edkeep<2>
stak = edkeep<3>
wild = edkeep<4> ; wild = not(not(wild))
chan = edkeep<5>
olda = edkeep<6>
shew = edkeep<7> ; shew = not(not(shew))
cmat = edkeep<8>
mmat = edkeep<9>
caseflag = not(edkeep<10>)
spaceflag = not(edkeep<11>)
blockflag = not(edkeep<12>)
* Get forced default flags
!&&&
! nick = true
!&&&
read temp from voc, '&ED.OPTIONS' then
line = upcase(trim(remove(temp, dlim)))
if line[1,1] eq 'X' then
loop
line = upcase(trim(remove(temp, dlim)))
begin case
case line[1,8] eq 'BLOCK ON'
blockflag = true
case line[1,9] eq 'BLOCK OFF'
blockflag = false
case line[1,7] eq 'CASE ON'
caseflag = true
case line[1,8] eq 'CASE OFF'
caseflag = true
case line[1,8] eq 'SPACE ON'
spaceflag = true
case line[1,9] eq 'SPACE OFF'
spaceflag = true
case line[1,7] eq 'SHOW ON'
shew = true
case line[1,8] eq 'SHOW OFF'
shew = true
end case
while dlim repeat
end
end
$ifdef universe
if unassigned(secure) then secure = '0'
$else
if assigned(secure) else secure = '0'
$endif
prepprog = '' ; prepflag = false
postprog = '' ; postflag = false
*********** UniData AE-style security start
$ifdef unidata
prepprog = getenv('PREPROG_AE_UDT')
$endif
$ifdef universe
execute 'ENV' capturing temp
xxno = dcount(temp,am)
for xx = 1 to xxno
line = temp<xx>
if field(line,'=',1) eq 'PREPROG_AE_UDT' then
prepprog = field(line,'=',2)
xxno = xx
end
next xx
$endif
$ifdef qm
* QM doesn't allow underscores in environmental variables, so
* this is the closest I can get to AE environmental variable name.
call !atvar(prepprog,'@PREPROG.AE.UDT')
$endif
* These next two tests are from the AE security documentation
* They may not be required, but you can set them up if you want
* if prepprog[1,3] eq 'AE_' then prepprog = ''
* if prepprog[len(prepprog)-2,3] ne '_AE' then prepprog = ''
if prepprog ne '' then prepflag = true
* The following security definitions mirror those of I_AE_SECURITY
* in UniData. I have only copied the functionality for SEC.SET
* being "NONE" (that is, this user cannot edit) and the general
* disabling of LOAD via the SEC.LOAD.FLG at first call to @PREPPROG;
* and inhibiting of file updates via subsequent @PREPPROG calls.
dim security(40)
equ sec.set to security(1) ;* set by preprog on very first call
* These fields are set in preprog
equ sec.read.flg to security(2) ;* read ok or not
equ sec.write.flg to security(3) ;* write ok or not
equ sec.delete.flg to security(4) ;* delete ok or not
equ sec.unload.flg to security(5) ;* unload ok or not
equ sec.load.flg to security(6) ;* load ok or not
equ sec.xeq.flg to security(7) ;* xeq ok or not
equ sec.xcom.flg to security(8) ;* xcoms ok or not
* the following 5 fields pass information to preprog & postprog,
equ sec.fn to security(9) ;* file name
equ sec.id to security(10);* record id
equ sec.dir.flg to security(11);* 1 if file is a directory
equ sec.newfile.flg to security(12);* 1 if new file name
equ sec.active.sel.flg to security(13);* 1 if select list is active
* this is how to make AE stop and return to calling program or ecl
equ sec.stop.flg to security(14);* set to 1 to force ae to stop
* for secondary calls to preprog; the first 3 cannot be changed
equ sec.call2.type to security(15);* 1 load, 2 unload
equ sec.fn2 to security(16);* second file - for load/unload
equ sec.id2 to security(17);* second id - for load or unload
equ sec.ok2.flg to security(18);* if 1, ok to load/unload
* 19-22 are used by postprog, which I have not implemented
equ sec.dict.flg to security(23) ;* 1 if fn is dict ...
equ sec.dict2.flg to security(24) ;* 1 if fn2 is dict ...
* field 25 is specific to UNIDATA AE, this and all other fields unused
* WARNING: preprog programs should not use the STOP or ABORT statements
* they should use the SEC.STOP.FLG to end nicely.
*********** UniData AE-style security end
* QM has it's own source control system depending on a callable program
* named SOURCE.CONTROL existing. It has the following fields
*
* DICT.FLAG - 'DICT' if a dictionary, otherwise ''
* FILE.NAME - name of file to be written
* RECORD.NAME - name of record to be written
* RECORD.DATA - the record to write
* CALLER - calling program identifier, I have used '3'
* WRITE.ALLOWED - 1 on call, returns 1 if write allowed and 0 otherwise
* UPDATED - 0 on call, returns 1 if RECORD.DATA is changed
source.control = false
$ifdef qm
if catalogued('SOURCE.CONTROL') then source.control = true
$else
* We can implement QM-style security if we want
if prepprog eq 'SOURCE.CONTROL' then source.control = true
$endif
if source.control then prepflag = false ; prepprog = ''
name = @logname
levl = @level
path = @path
term = @tty
whom = @userno
acct = @who
* This is to display unprintable characters safely
badc = char(255)
for xx = 0 to 31 ; badc := char(xx) ; next xx
for xx = 127 to 250 ; badc := char(xx) ; next xx
gudc = str('~',len(badc))
* eeePC does not distinguish between these
if index(upcase(system(7)),'EEEPC',1) then
badc := char(251):char(252):char(253); gudc := '[\]'
end else
badc := char(251):char(252):char(253)
gudc := char(179):char(178):char(185)
end
* The yes/no can be language independant!
yes = 'Yes' ; yes = upcase(trim(yes))
no = 'No' ; no = upcase(trim(no))
ny = '(':no[1,1]:'/':yes[1,1]:') >'
* Want to see these thing in a single page
presnumb = system(3)-2
if presnumb gt 20 then presnumb = 20
looknumb = presnumb; channumb = presnumb
* Want this to be no more than five pages
staknumb = (presnumb+1)*5+1
* Parse the command line - long way in before work starts, eh?
* Anything in brackets is an option - but we do not use them at all.
* "verb" is how this was called so it should work to call again
verb = ''
$ifdef qm
$include parser.h
call !parser(parser$reset, 0, @sentence, 0)
opts = false
options = ''
sentence = ''
loop
call !parser(parser$get.token, type, param, keyword)
until type eq parser$end do
begin case
case type eq 4 ; opts = true
case type eq 5 ; opts = false
case opts ; options<-1> = param
case 1 ; sentence<-1> = param
end case
repeat
$else
rest = @sentence
keepquot = false
gosub parse.rest
sentence = bite
temp = dcount(sentence,am)
options = sentence<temp>
if options[1,1] eq '(' then
options = field(field(options,'(',2),')',1)
sentence = delete(bite,temp,0,0)
end else options = ''
$endif
if options ne '' then options = ' (':options:')'
* The C option allows the user to build paragraphs
* using DATA statements to control the editor.
* Otherwise they are restricted to an interactive mode.
if index(upcase(options),'C',1)
then editpage = false
else editpage = true
if upcase(sentence<1>) eq 'RUN' then
verb = sentence<1>:' ':sentence<2>:' '
sentence = delete(sentence,1,0,0)
sentence = delete(sentence,1,0,0)
end
verb = verb:sentence<1>
sentence = delete(sentence,1,0,0)
* Check if a viewing verb has been used
* If so, we can turn off both security systems (I mope I'm right!)
* The security flags are set safe, and each command is tested
* individually, so I think it's pretty safe.
* FORMAT is still allowed, but no other change command.
viewflag = false ; view = 'edit'
locate(upcase(verb),viewverb;posn) then
viewflag = true
view = 'view'
source.control = false
prepflag = false
end
* OR, they used the V option
if index(upcase(options),'V',1) then
viewflag = true
view = 'view'
source.control = false
prepflag = false
end
* HELP location
help.def = '2.00'
help = ''
pagehelp = ''
fnam = sentence<1>
sentence = delete(sentence,1,0,0)
if upcase(fnam) eq 'DICT' then
fnam = 'DICT ':sentence<1>
sentence = delete(sentence,1,0,0)
end
idlist = sentence
if system(11) and idlist ne '' then
crt 'A select list was active, but specific ids were entered.'
crt 'Select list will be ignored.'
crt str('-',len('Select list will be ignored.'))
clearselect
end
open 'AE_COMS' to acom else
$ifdef qm
execute 'CREATE.FILE AE_COMS'
$else
execute 'CREATE.FILE AE_COMS 1 7'
$endif
open 'AE_COMS' to acom else stop 'Cannot open ':'AE_COMS'
test = @(0,0)
end
* Get file
loop
got.file = false
if fnam eq '' then
stub = 'File name? '
gosub get.rope; fnam = rope; crt
end
if fnam eq '' then stop
dprt = field(fnam,' ',1)
fprt = field(fnam,' ',2)
if fprt eq '' then fprt = dprt ; dprt = ''
open dprt, fprt to file then
got.file = true
end else
open upcase(dprt),upcase(fprt) to file then
got.file = true
end else
crt 'Cannot open ':'"':fnam:'"'
fnam = ''
end
end
until got.file do
repeat
if fileinfo(file,3) eq '4' then bleach = false else bleach = true
bleach = upcase(fileinfo(file,2))
if bleach[2] = 'BP' or bleach[7] = 'SFPROGS'
then bleach = false
else bleach = true
* Get the record
if idlist eq '*' then
idlist = ''
execute 'SELECT ':dprt:' ':fprt
test = @(0,0)
end
if system(11) then
eof = false
loop
readnext id else eof = true
until eof do
idlist<-1> = id
repeat
end
loop
killsign = false
if idlist eq '' then
stub = 'Record name? '
gosub get.rope; rest = rope ; crt
keepquot = false
gosub parse.rest
idlist = bite
bite = '' ; rest = ''
end
idcnt = dcount(idlist,am)
for id = 1 to idcnt until killsign
item = idlist<id>
gosub edit.item
next id
while killsign do
idlist = ''
repeat
edkeep = pres:am:look:am:stak:am:wild:am:chan:am:olda:am:shew
edkeep := am:cmat:am:mmat:am:not(caseflag):am:not(spaceflag)
edkeep := am:not(blockflag):am:lower(kept)
stop
* SUBROUTINES
* ***********
edit.item:
stopsign = false
here = 0 ; dnum = 0
beg = 0 ; fin = 0 ; krj = ''
crt
if idcnt gt 1 then crt '<':id:'/':idcnt:'> ':
if prepflag then
if secure eq '0' then
mat security = ''
sec.set = ''
call @prepprog(mat security)
if sec.set eq 'NONE' then stop
if sec.stop.flg then stop
secure = sec.set
end
mat security = ''
sec.set = secure
if sec.set then
sec.fn = fprt
sec.id = item
sec.dir.flg = fileinfo(file,3) = '4'
sec.newfile.flg = false
sec.active.sel.flg = false
sec.dict.flg = (dprt = 'DICT')
call @prepprog(mat security)
if sec.stop.flg then stop
if not(sec.read.flg) then return
end
end else
sec.stop.flg = false
sec.read.flg = true
sec.write.flg = true
sec.delete.flg = true
sec.xcom.flg = true
sec.unload.flg = true
sec.load.flg = true
sec.xeq.flg = true
sec.ok2.flg = true
* Apply the viewing flag
if viewflag then
crt 'VIEW ONLY - NO UPDATES ALLOWED'
sec.write.flg = false
sec.delete.flg = false
sec.xcom.flg = false
sec.unload.flg = false
sec.load.flg = false
sec.xeq.flg = false
sec.ok2.flg = false
end
end
readu this from file, item locked goto locked.record then
lock = true
carry.on:
gosub parse.record
crt 'Top of "':item:'" in "':fnam:'", ':last:' lines, ':len(this):' characters.'
end else
lock = true
this = ''
gosub parse.record
crt 'Top of new "':item:'" in "':fnam:'".'
end
orig = this
gosub get.lfmt
* Edit the record
loop
if mode<1> eq 'PAGE' then
pcol = rem(pchr-1,span)
prow = here+1-ptop
crt @(60,0):ceol:revb:mode<2>:revf:' ':fmt(here,'R#4'):
crt ',':fmt(pchr,'L#4'):
bite = temp[pchr,1]
if bite ne '' then crt ' (':seq(bite):')':
crt @(pcol,prow):
gosub get.page.comd
if mode eq 'LINE' then
crt bott:'Line Editor Mode':
if that ne this then
crt ' - CHANGES HAVE BEEN MADE':
oops = that ; oopc = 'PE'
oopl = savl<1> ; oopf = savl<2>
oopb = beg:am:fin ; oopk = krj
end
crt
that = ''
gosub display.line
end
end
if mode<1> eq 'LINE' then
* Get the command
if x$cc ne '' then
comi = x$cc<1>
x$cc = delete(x$cc,1,0,0)
end else
if mode<1> eq 'PAGE' then continue
if salt ne '' then
comi = salt<1,1,1>; del salt<1,1,1>
end else
stub = prmt:': '; heap = true
gosub get.rope; comi = rope; heap = false
end
if macn then macc<1,1,-1> = comi
end
gosub parse.command
if not(numb eq '' or numb matches '1N0N') then
crt ; gosub bad.command
continue
end
if comd eq '' then
gosub null.command
if comd eq '' then continue
end
* Save command to list
if comi ne '' and comi ne stak<1,1> and comd ne 'D' then
stak = insert(stak,1,1,0,comi)
stak = delete(stak,1,staknumb,0)
end
* Apply the command
if comd ne 'R' then crt
if comd matches '1N0N' then
here = comd
if here gt last then here = last
gosub display.line
continue
end
loop
redo = false
first = comd[1,1]
posn = index('ABCDEFGHIJKLMNOPQRSTUVWXYZ',first,1)
on posn gosub a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
while redo do repeat
if stopsign then release file, item ; lock = false ; return
end
repeat
return
parse.command:
comi = trimf(comi)
dlim = oconv(oconv(comi,'MC/A'),'MC/N')[1,1]
if dlim eq '' then
rest = ''
comd = upcase(comi)
end else
posn = index(comi,dlim,1)
rest = comi[posn+1,huge]
comd = upcase(comi[1,posn-1])
end
temp = oconv(comd,'MCN')[1,1]
if temp ne '' then
temp = index(comd,temp,1)
numb = comd[temp,huge]
comd = comd[1,temp-1]
end else numb = ''
return
parse.line:
if line eq comdmark then line = ''
xx = 1
loop
temp = index(line,'^',xx)
while temp do
bite = line[temp,5]
if bite matches '"^^"3N' then
line = line[1,temp-1]:line[temp+1,len(line)]
xx += 1
end else
bite = bite[1,4]
if bite matches '"^"3N' then
line= line[1,temp-1]:char(bite[2,3]):line[temp+4,len(line)]
end else xx += 1
end
repeat
return
a: begin case
case comd eq 'A' ; * append
if viewflag then gosub viewonly ; return
if rest eq '' then rest = olda<1,1>
if rest eq '' then
crt 'No previous append command to repeat'
gosub bad.comd
return
end
olda = rest:vm:dlim
line = rest ; gosub parse.line ; rest = line
chng = 0 ; save = here ; savl = last
dnum = 1
gosub set.bounds
for here = dawn to dusk
gosub get.line
line = line:rest
if not(chng) then gosub savethis
memr(cell)<lnum> = line
chng += 1
if shew or dnum lt plen then gosub display.line
next here
here = dusk
if chng then
gosub reset.record
crt chng:' lines changed - now at ':here
end
case 1 ; gosub bad.command
end case
return
b: begin case
case comd eq 'B' and dlim eq '' ; * bottom
here = last ; gosub display.line
case index('\B\BD\BK\BR\BS\','\':comd:'\',1) ; * break line
if viewflag then gosub viewonly ; return
if rest eq '' then
crt 'The second field is empty.'
gosub bad.comd
return
end
chng = 0 ; save = here ; savl = last ; show = ''
gosub set.bounds
for here = dusk to dawn step -1
gosub get.line
posn = index(line,rest,1)
if posn then
left = line[1,posn-1]
temp = line[posn+len(rest),len(line)]
if temp ne '' or comd eq 'BS' then
begin case
case comd eq 'BD' ; line = left:rest
case comd eq 'BK' ; line = temp
case comd eq 'BR' ; line = temp:left:rest
case comd eq 'BS' ; line = temp:rest:left
case 1 ; line = left:rest
end case
memr(cell)<lnum> = line
show = insert(show,1,0,0,here)
numb += 1
chng += 1
if comd eq 'B' then
dusk += 1
last += 1
lnum += 1
line = temp
gosub insert.line
end
end
end
next here
if chng then
gosub savethis
gosub reset.record
zzno = dcount(show,am)
savl = 0 ; dnum = 1
for zz = 1 to zzno
here = show<zz> + savl
if shew or dnum lt plen then gosub display.line
if comd eq 'B' and zzno gt 1 then
here += 1
savl += 1
if shew or dnum lt plen then gosub display.line
end
next zz
show = ''
end
if comd eq 'B'
then here = dusk + numb - 2
else here = dusk
if here gt last then here = last
if chng then
crt 'Split ':numb:' records. Now at line ':here
end
gosub get.line
case index('\BC\BCD\BCK\BCR\BCS\','\':comd:'\',1) ; * Break @ Column
if viewflag then gosub viewonly ; return
posn = trim(field(rest,dlim,1))
if not(posn matches '1n0n') then
crt 'No column position given'
gosub bad.comd
return
end
chng = 0 ; save = here ; show = ''
gosub set.bounds
for here = dusk to dawn step -1
gosub get.line
if len(line) gt posn then
left = line[1,posn-1]
temp = line[posn+1,len(line)]
if temp ne '' or comd eq 'BCS' then
begin case
case comd eq 'BCD' ; line = left:rest
case comd eq 'BCK' ; line = temp
case comd eq 'BCR' ; line = temp:left:rest
case comd eq 'BCS' ; line = temp:rest:left
case 1 ; line = left:rest
end case
memr(cell)<lnum> = line
show = insert(show,1,0,0,here)
numb += 1
chng += 1
if comd eq 'BC' then
dusk += 1
last += 1
lnum += 1
line = temp
gosub insert.line
end
end
end
next here
if chng then
gosub savethis
gosub reset.record
zzno = dcount(show,am)
savl = 0 ; dnum = 1
for zz = 1 to zzno
here = show<zz> + savl
if shew or dnum lt plen then gosub display.line
if comd eq 'BC' and zzno gt 1 then
here += 1
savl += 1
if shew or dnum lt plen then gosub display.line
end
next zz
show = ''
end
if comd eq 'BC'
then here = dusk + numb - 2
else here = dusk
if here gt last then here = last
if chng then
crt 'Split ':numb:' records. Now at line ':here
end
gosub get.line
case comd eq 'BLEACH' ; * change BLEACH flag
rest = upcase(rest)
begin case
case rest eq 'ON' ; bleach = true
case rest eq 'OFF' ; bleach = false
case 1 ; bleach = not(bleach)
end case
if bleach
then crt 'Colours disabled'
else crt 'Colours enabled'
case comd eq 'BLOCK' ; * change BLOCK flag
rest = upcase(rest)
begin case
case rest eq 'ON' ; blockflag = true
case rest eq 'OFF' ; blockflag = false
case 1 ; blockflag = not(blockflag)
end case
if blockflag then
crt 'Verification of block actions enabled'
end else crt 'Verification of block actions disabled'
case 1 ; gosub bad.command
end case
return
c: begin case
case comd eq 'C' ; * change
if viewflag then gosub viewonly ; return
if numb eq '' and dlim eq '' then
comd = 'RA'
comi = 'RA1'
numb = 1
end
gosub change.command
case comd eq 'CAT' ; comd = 'J' ; redo = true
case comd eq 'CASE' ; * change casing flag for 'L'
rest = upcase(rest)
begin case
case rest eq 'ON' ; caseflag = true
case rest eq 'OFF' ; caseflag = false
case 1 ; caseflag = not(caseflag)
end case
if caseflag then
crt 'Searches are case-sensitive'
end else crt 'Searches are not case-sensitive'
case comd eq 'CD' ; * command delimiter display (change)
if dlim eq '' then
crt 'Command delimiter is ':
end else
temp = '`,;#$%&~|[]{}/"':"'"
if index(temp,dlim,1) then
comdmark = dlim
crt 'Command delimiter is ':
end else
crt dlim:' is not a valid command delimiter.'
crt 'Characters available for delimiters: ':temp
crt 'Characters reserved for other uses: \.*!?-+=^@<>_:'
crt 'Command delimiter is ':
end
end
if comdmark eq '"'
then crt "'":comdmark:"'"
else crt '"':comdmark:'"'
case comd eq 'CLEAR' ; * Clear the kept buffer
if kept eq ''
then crt 'Nothing in KEPT buffer'
else crt 'KEPT buffer cleared'
kept = ''
case comd = 'COPY' ; * copy to kept buffer
if comd eq upcase(comi) then
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd; return
end
rest = beg
numb = fin-beg+1
end
rest = trim(rest)
if numb eq '' then gosub parse.atts
if rest eq '' then rest = here
if not(rest matches '1N0N') or numb eq '' then
crt 'Formats are: "COPY" (from <> block) or "COPYn" or "COPYn/s" or "COPY/s/f".'
gosub bad.comd ; return
end
if numb lt 1 then
crt 'Nothing done - no lines selected.'
comi = ''; return
end
if numb gt last then
crt 'Nothing done - record does not have that many lines.'
comi = '' ; return
end
kept = field(this,am,rest,numb)
numb = dcount(kept,am)
if numb then crt numb:' lines copied to KEPT buffer starting at line ':rest
case comd eq 'CM' ; * changematch command
if viewflag then gosub viewonly ; return
if rest eq '' then
if cmat eq '' then
crt 'No previous ChangeMatch command to repeat.'
comi = ''
return
end else
dlim = cmat<1,1>
rest = cmat<1,2>
numb = cmat<1,3>
end
end
gosub changematch.command
case comd eq 'COL' ; * column display
temp = ''
for xx = 1 to 9
temp = temp:space(9):xx
next xx
if lfmt
then crt begn:space(llen+2):temp[1,span-llen-2]
else crt begn:temp[1,span]
temp = str('1234567890',10)
if lfmt
then crt begn:space(llen+2):temp[1,span-llen-2]
else crt begn:temp[1,span]
temp = ''
case comd eq 'COUNT' ; * show the count of a string
line = rest ; gosub parse.line ; rest = line
if rest eq '' then
crt 'No string given to count'
gosub bad.comd ; return
end
gosub set.bounds
if not(caseflag) then rest = upcase(rest)
temp = 0
for here = dawn to dusk
gosub get.line
if caseflag
then temp = temp + count(line,rest)
else temp = temp + count(upcase(line),rest)
next here
here = dusk
crt temp:' occurances of string.'
case comd eq 'CRT' ; * insert crt line for programmer
if viewflag then gosub viewonly ; return
if rest eq '' then
crt 'You have not said what to put on CRT line!'
comi = ''
return
end
gosub savethat
here += 1 ; last += 1 ; lnum += 1
if dlim ne '"' and dlim ne '\' then dlim = "'"
line = 'CRT ':dlim:rest:' = ':dlim:':':rest
gosub insert.line
gosub reset.record
gosub display.line
case comd eq 'CUT' ;* Move lines to kept buffer
if viewflag then gosub viewonly ; return
if comd eq upcase(comi) then
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd; return
end
rest = beg
numb = fin-beg+1
end
rest = trim(rest)
if numb eq '' then gosub parse.atts
if rest eq '' then rest = here
if not(rest matches '1N0N') or numb eq '' then
crt 'Formats are: "CUT" (from <> block) or "CUTn" or "CUTn/s" or "CUT/s/f".'
gosub bad.comd; return
end
if numb gt last then
crt 'Nothing done - record does not have that many lines.'
comi = '' ; return
end
kept = field(this,am,rest,numb)
numb = dcount(kept,am)
dawn = rest
dusk = rest+numb-1
gosub delete.lines
if numb then crt numb:' lines moved to KEPT buffer starting at line ':rest
case 1 ; gosub bad.command
end case
return
d: begin case
case comd eq 'D' ; * display current line
if here gt last then here = last
gosub display.line
case comd eq 'DE' ; * delete lines
if viewflag then gosub viewonly ; return
chng = 0 ; save = here ; savl = last
if rest ne '' then
patt = rest
cto = ''
cfrom = 'DE'
gosub cm.del.entry
return
end
gosub set.bounds
gosub delete.lines
here = dawn
if here gt last then
here = last
crt 'Bottom. Line ':here:' was above the last delete.'
end else
crt 'At line ':here:'. Deleted ':chng:' lines.'
gosub display.line
end
$ifdef qm
case comd eq 'DISPLAY' ; * insert display line for programmer
if viewflag then gosub viewonly ; return
if rest eq '' then
crt 'You have not said what to put on DISPLAY line!'
comi = ''
return
end
gosub savethat
here += 1 ; last += 1 ; lnum += 1
if dlim ne '"' and dlim ne '\' then dlim = "'"
line = 'DISPLAY ':dlim:rest:' = ':dlim:':':rest
gosub insert.line
gosub reset.record
gosub display.line
$endif
case comd eq 'DROP' ; * remove the block
if viewflag then gosub viewonly ; return
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd ; return
end
if beg le 1 then
temp = 0
end else
temp = index(this,am,beg-1)
if not(temp) then
crt 'Error - Block start line not defined' ; *Cannot find beginning of block
gosub bad.comd ; return
end
end
if fin eq last then
temp -= 1
temp<2> = len(this)
end else
temp<2> = index(this,am,fin)
end
if not(temp<2>) then
crt 'Error - Block end line not defined' ; *Cannot find end of block
gosub bad.comd ; return
end
numb = fin - beg + 1
if blockflag then
if beg eq fin
then stub = 'Delete line ': beg:' '
else stub = 'Delete block from line ': beg:' to line ': fin:'? '
gosub get.answ
if answ ne yes[1,1] then
crt 'Block command cancelled.'
return
end
end
dawn = beg; dusk = fin
gosub delete.lines
crt 'Dropped (deleted) ':numb:' lines.'
gosub display.line
case comd eq 'DTX' ; * decimal to hex
if not(rest matches '1N0N') then
crt 'Numeric value required'
gosub bad.comd ; return
end
if len(rest) gt 9 then
crt 'Must be less than one billion (1,000,000,000)'
gosub bad.comd ; return
end
$ifdef universe
crt dtx(rest)
$else
crt oconv(rest,'MX')
$endif
case comd eq 'DUP' ; * duplicate previous line
if viewflag then gosub viewonly ; return
if here lt 1 then
crt 'No current line'
gosub bad.comd ; return
end
if numb eq '' and rest matches '1N0N' then numb = rest
if numb lt 1 then numb = 1
gosub savethat
gosub get.line
for xx = 1 to numb
gosub insert.line
last += 1
next xx
gosub reset.record
crt 'Inserted ':numb:' copies of line ':here:' after line ':here:'. Still at ':here:'.'
case 1 ; gosub bad.command
end case
return
e: begin case
case comd eq 'EC' ; * edit called program (in this file)
if here lt 1 then here = 1
gosub get.line
line = trim(line)
temp = upcase(line)
good = index(temp,'CALL ',1)
if good then line = trim(line[good+5,huge])
line = trim(field(line,'(',1))
if index(line,' ',1) then good = false
if line[1,1] eq '@' then
crt 'Leading "@" is logical pointer'
good = false
end
if not(good) then
crt 'The EC command requires lines in format "CALL ID" or "CALL ID(..."'
gosub bad.comd ; return
end
* readv temp from file, line, 1 else
* crt '"':line:'" is not in this file'
* gosub bad.comd ; return
* end
* execute verb:' ':fnam:' ':line
readv temp from file, line, 1 then
execute verb:' ':fnam:' ':line:options
end else
test = false
readv vlin from voc, line, 2 then
vcnt = dcount(vlin,'/')
vlin = field(vlin,'/',vcnt-1)
vlin = vlin[1,len(vlin)-2]
test = trans(vlin,line,-1,'X')
end
if test then
execute verb:' ':vlin:' ':line:options
end else
crt '"':line:'" is not in this file'
gosub bad.comd ; return
end
end
***
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
case comd = 'ECS' ; * edit command stack
ttid = whom:'_':levl:'_commands'
temp = raise(stak)
write temp on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing command stack'
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read temp from acom, ttid else temp = ''
temp = field(temp,am,1,staknumb-1)
stak = lower(temp)
delete acom, ttid
case comd eq 'EDITPAGE'
editpage = not(editpage)
*>
if editpage then
begn = @(0) ; goup = @(-10)
prmt = '*':str('-',llen-1)
end else
begn = char(13) ; goup = ''
prmt = str('-',llen)
end
crt 'editpage = ':editpage
*>
case comd eq 'EF' ; * edit fields
numb = numb + 0
if numb lt 0 or numb gt 255 then
crt numb:' is outside range 0-255'
comi = ''
return
end
vmrk = char(numb)
vals = 'char':numb
gosub edit.fields
vmrk = char(numb); gosub reset.fields
case comd eq 'EI' ; * edit included code
if here lt 1 then here = 1
gosub get.line
line = field(line,';',1)
line = trim(line)
good = true
temp = field(line,' ',1)
temp = upcase(temp)
if temp ne 'INCLUDE' and temp ne '$INCLUDE' then good = false
line = trim(line[len(temp)+1,len(line)])
begin case
case dcount(line,' ') gt 3 ; good = false
case dcount(line,' ') eq 3
if field(line,' ',1) ne 'DICT' then good = false
case dcount(line,' ') eq 1
readv test from file, line, 1 then
line = fnam:' ':line
end else
test = trans('SYSCOM',line,1,'X')
if test ne ''
then line = 'SYSCOM ':line
else line = fnam:' ':line
end
end case
if not(good) then
crt 'The EI command requires lines in format "$IN... {DICT} {FN} ID"'
gosub bad.comd ; return
end
execute verb:' ':line:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
case comd eq 'EIT' ; * edit i-types (@)
if dprt and here eq 2 and upcase(this[1,1]) else
crt 'EIT is only for line 2 of a dictionary I-type'
return
end
gosub get.line ; temp = line
gosub split.itype
ttid = whom:'_':levl:'_IType.in.line#':here
write bite on acom, ttid on error gosub writerr ; return
crt view:'ing IType as fields...':
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read line from acom, ttid else line = ''
delete acom, ttid
vmrk = ';'; gosub reset.fields
* case comd eq 'EM' ; * edit MESSAGES
* if numb eq '' and rest matches '1N0N' then numb = rest
* if numb then
* execute verb:' MESSAGES ':numb:options
* end else
* if here lt 1 then here = 1
* gosub get.line
* line = trim(line)
* temp = upcase(line)
* good = index(temp,'SYSMSG',1)
* if good then line = trim(line[good+6,huge])
* line = trim(field(line,'(',2))
* line = trim(field(field(line,')',1),',',1))
* if not(line matches '1N0N') then good = false
* if not(good) then
* crt 'The EM command requires lines in format "...sysmsg(1N0N..."'
* crt 'Or a command like EMnnnn (nnnn is a message number)'
* gosub bad.comd ; return
* end
* execute verb:' MESSAGES ':line:options
* end
* test = @(0,0)
* crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
case comd = 'EK' ; * edit kept buffer
ttid = whom:'_':levl:'_keptbuffer'
write kept on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing kept buffer':
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read kept from acom, ttid else kept = ''
delete acom, ttid
case comd = 'EPR' ; * edit prestores
numb = numb + 0
if numb lt 0 or numb gt presnumb then
crt 'PRestore must be in range 1-':presnumb:'.'
gosub bad.comd ; return
end
ttid = whom:'_':levl:'_prestores'
temp = raise(pres)
if numb then
bite = raise(temp<numb>)
write bite on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing prestore ':view:
end else
write temp on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing prestores':
end
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
if numb then
read bite from acom, ttid else bite = ''
temp<numb> = lower(bite)
end else
read temp from acom, ttid else temp = ''
end
pres = lower(temp)
delete acom, ttid
case comd = 'ESS' ; * edit search stack
ttid = whom:'_':levl:'_searches'
temp = raise(look)
write temp on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing search stack':
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read temp from acom, ttid else look = ''
look = lower(temp)
delete acom, ttid
case comd eq 'ESV' ; * edit subvalues
vmrk = sm ; vals = 'subvalues'
gosub edit.fields
vmrk = sm; gosub reset.fields
case comd eq 'ET' ; * edit tabs
ttid = whom:'_':levl:'_tabs'
xxno = dcount(krj<1>,@vm)
temp = ''
for xx = 1 to xxno
temp<xx> = krj<2,xx>:' ':krj<1,xx>
next xx
write temp on acom, ttid on error crt 'WRITE failure - file not updated' ; return
crt view:'ing line tabs':
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read temp from acom, ttid else temp = ''
xxno = dcount(temp,@am)
krj = @am:@am:krj<3>
yy = ''
for xx = 1 to xxno
bite = trim(temp<xx,1,1>)
left = field(bite,' ',1)
rest = field(bite,' ',2,99)
if left matches '1N0N' then left += 0 else left = 0
if left gt last then left = 0
if left then
yy += 1
if rest eq '' then rest = 'T':left
krj<1,yy> = rest
krj<2,yy> = left
end
next xxno
if krj<3> gt yy then krj<3> = yy
if krj<1> ne '' and krj<3> lt 1 then krj<3> = 1
delete acom, ttid
case comd eq 'EV' ; * edit values
vmrk = vm ; vals = 'values'
gosub edit.fields
vmrk = vm; gosub reset.fields
case comd eq 'EW' ; * edit words (as defined by wordmark)
vmrk = wordmark ; vals = 'words'
gosub edit.fields
vmrk = wordmark; gosub reset.fields
* Various forms for quitting
case comd eq 'EX' or comd = 'EXIT' ; comd = 'Q' ; redo = true
case comd eq 'EXK' or comd = 'EXITK' ; comd = 'QK' ; redo = true
case 1 ; gosub bad.command
end case
return
f: begin case
case comd eq 'FD' ; * delete item
if viewflag then gosub viewonly ; return
if not(sec.delete.flg) then
crt 'Delete disabled'
comi = ''
return
end
gosub write.record
case comd eq 'FILE' ; comd = 'SV' ; redo = true
case comd[1,2] eq 'FI' ; * file item
if viewflag then gosub viewonly ; return
if not(sec.write.flg) then
crt 'File disabled'
comi = ''
return
end
temp = comd[3,len(comd)]
convert 'BCRDL' to '' in temp
if temp eq '' then gosub write.record else gosub bad.command
case comd eq 'FL' or comd eq 'FLA' ; * find labels
if not(caseflag) then rest = upcase(rest)
if index(comd,'A',1) then
bump = -1
dawn = here - 1
if dawn lt 1 then return
if numb then dusk = here - numb else dusk = 1
if dusk lt 1 then dusk = 1
end else
bump = 1
dawn = here + 1
if dawn gt last then dawn = 1
if numb then dusk = dawn + numb else dusk = last
if dusk gt last then dusk = last
end
for here = dawn to dusk step bump
gosub get.line
gosub find.label
if not(caseflag) then temp = upcase(temp)
if temp ne '' then
if rest eq '' or temp matches rest then
gosub display.line
if not(numb) then return
end
end
next here
crt
gosub display.line
case comd eq 'FM' or comd eq 'FMA' ; * find match command
gosub get.line
* Get rid of any label
gosub find.label
thisline = trimf(line)
if temp ne '' then
thisline = thisline[len(temp)+1,huge]
if thisline[1,1] eq ':' then thisline = thisline[2,huge]
thisline = trimf(thisline)
end
* Get the first word on the line
word = field(trim(upcase(thisline)),' ',1)
begin case
case rest ne ''
seek = upcase(rest)
case word[1,1] eq '*' or word[1,1] eq '!'
seek = word[1,1]
case 1
locate(word,fm.words;posn) then
if index(comd,'A' ,1) then
seek = fm.finda<posn>
end else
seek = fm.findf<posn>
end
end else
locate(word,endwords;posn) then
seek = 'END'
end else
crt 'Starting word "':word:'" unknown'
gosub bad.comd ; return
end
end
end case
if seek eq '' then
crt word:' has no matching word for ':comd
gosub bad.comd ; return
end
posn = index(upcase(line),word,1)
xxno = dcount(seek,vm)
for xx = 1 to xxno
seek<1,xx> = space(posn-1):seek<1,xx>
next xx
if index(comd,'A',1) then
bump = -1
dawn = here - 1
if dawn lt 1 then return
dusk = 1
end else
bump = 1
dawn = here + 1
if dawn gt last then return
dusk = last
end
save = here
for here = dawn to dusk step bump
gosub get.line
line = upcase(line)
if line[1,1] ne '' then
temp = field(line,' ',1)
if num(temp) or temp[len(temp),1] eq ':' then
temp = len(temp)
line = space(temp):line[temp+1,len(line)]
end
end
for xx = 1 to xxno
slen = len(seek<1,xx>)
if line[1,slen] eq seek<1,xx> then
if trim(line[slen+1,1]) eq '' then
gosub display.line
return
end
end
next xx
next here
here = save
gosub get.line
case comd eq 'FOLD' ; * fold the line
if viewflag then gosub viewonly ; return
chng = 0 ; save = here ; savl = last
if dlim ne '' then fold = ''
if rest eq '' then rest = fold
if rest eq '' then rest = span-llen-2
if not(rest matches '1N0N') then
crt 'Non-numeric length - try HELP FOLD.'
comi = ''
return
end
fold = rest
gosub get.line
crt 'FOLD line to length ':fold
bite = line
gosub parse.bite
gosub check.line
if chng then gosub reset.record
case comd eq 'FOR' or comd eq 'FORMAT' ; * format this item
rest = upcase(rest)
temp = index(rest,'-M',1)
if temp then fr(1) = field(rest[temp+2,huge],' ',1) ; fr(2) = ''
if not(fr(1) matches '1N0N') then fr(1) = ''
if fr(1) eq '' then
temp = this<1>
fr(1) = len(temp) - len(trimf(temp))
end
temp = index(rest,'-I',1)
if temp then fr(2) = field(rest[temp+2,huge],' ',1)
if not(fr(2) matches '1N0N') then fr(2) = ''
if fr(2) eq '' then
fr(2) = int((fr(1)+1)/2)
if fr(2) lt 2 then fr(2) = 2
end
if index(rest,'-A',1) then fr(9) = true else fr(9) = ''
if index(rest,'-N',1) then fr(10) = true else fr(10) = ''
if index(rest,'-C',1) then
fr(1) = 0
fr(2) = 1
fr(9) = true
fr(10) = true
end
if last lt 1 then return
gosub savethat
crt 'Margin=':fr(1):', Indentation=':fr(2)
gosub indenter
gosub set.record
case 1 ; gosub bad.command
end case
return
g: begin case
case comd eq 'G' ; * Go to line
if numb eq '' then
if dlim eq '<' and beg ne '' then here = beg
if dlim eq '>' and fin ne '' then here = fin
end else here = numb
if here gt last then here = last
gosub display.line
case 1 ; gosub bad.command
end case
return
h: begin case
case comd eq 'H' or comd eq 'HELP'
gosub show.help
case comd eq 'HEX' ; * show this line in hexadecimal
if not(here) then return
gosub get.line
temp = ''
xxno = len(line)
for xx = 1 to xxno
bit = line[xx,1]
$ifdef universe
bit = dtx(seq(bit))
$else
bit = oconv(seq(bit),'MX')
$endif
$ifdef unidata
bit = fmt(bit,'2/0R')
$else
bit = fmt(bit,'R%2')
$endif
temp<1> = temp<1>:bit[1,1]
temp<2> = temp<2>:bit[2,1]
next xx
if lfmt then crt fmt(here,lfmt):': ':
crt temp<1>
if lfmt then crt space(llen+2):
crt temp<2>
temp = ''
case 1 ; gosub bad.command
end case
return
i: begin case
case comd eq 'I' ; * insert lines
if viewflag then gosub viewonly ; return
chng = 0 ; save = here ; savl = last
if rest ne '' then
if numb lt 1 then numb = 1
inum = numb
gosub get.line
if not(chng) then gosub savethis
if here gt 0 then
memr(cell)<lnum> := str(am:rest,inum)
end else memr(1)<1> = str(rest:am,inum):memr(1)<1>
if here le beg then beg += inum
if here le fin then fin += inum
yyno = dcount(krj<1>,vm)
for yy = 1 to yyno
if krj<2,yy> gt here then krj<2,yy> += inum
next yy
here = here + inum
gosub reset.record
gosub get.line
gosub display.line
crt 'At line ':here:'. ':inum:' lines inserted, bottom now at line ':last:'.'
end else
if nill ne '' then
crt 'Terminate input with "':nill:'"'
end
!&&&
! if nick then gosub get.line
!&&&
loop
!&&&
! if nick
! then pill = space(len(line)-len(trimf(line)))
! else pill = ''
! pick = pill
! pill := nill
!&&&
new1 = here + 1
stub = new1:'='
if lfmt then stub = fmt(new1,lfmt):'='
gosub get.rope; line = rope
!&&&
until line eq nill do
! until line eq nill or line eq pill do
!&&&
gosub parse.line
last += 1
here += 1
lnum += 1
if not(chng) then gosub savethis
chng += 1
gosub insert.line
temp = len(last)
if lfmt then
if temp gt 3 and temp ne llen then gosub get.lfmt
end
if line eq nill then
crt begn:
if lfmt then crt fmt(new1,lfmt):'= ':
end
crt
numb -= 1
if numb eq 0 then exit
repeat
crt begn:ceol:
end
if chng then gosub reset.record
case comd eq 'IC' ; * iconv
if viewflag then gosub viewonly ; return
if rest eq '' then
crt 'No conversion given'
gosub bad.comd ; return
end
ccom = '*':rest ; gosub conv.command
case comd eq 'IN' ; * insert from execute
if viewflag then gosub viewonly ; return
if trim(rest) eq '' then
crt 'No external command given'
comi = '' ; return
end
execute rest capturing bite
test = @(0,0)
numb = dcount(bite,am)
if numb then
gosub savethat
this = insert(this,here+1,0,0,bite)
gosub set.record
crt 'Inserted ':numb:' lines; still at line ':here:'.'
end else
crt 'Nothing done - no output from command.'
comi = '' ; return
end
case 1 ; gosub bad.command
end case
return
j: begin case
case comd eq 'J' ; * join lines
if viewflag then gosub viewonly ; return
if dlim ne '' then
line = rest ; gosub parse.line ; join = line
end
if here and here lt last then
chng = 0 ; save = here ; savl = last
gosub get.line
test = line
here += 1
gosub set.bounds
for here = dawn to dusk
gosub get.line
test = test:join:line
next here
gosub delete.lines
if chng eq 0 then return
here = save
oopl = here
gosub get.line
memr(cell)<lnum> = test
gosub reset.record
end
gosub display.line
case 1 ; gosub bad.command
end case
return
k: begin case
case comd eq 'KEEP' or comd eq 'KEEPA'
gosub get.load
if temp eq '' then return
if comd[len(comd),1] ne 'A' then
gosub get.lines
if not(temp) then return
end
kept = temp
temp = dcount(temp,am)
crt 'At line ':here:', ':temp:' lines loaded into kept buffer.'
temp = ''
case comd eq 'KEPT' or comd eq 'K' ; * display kept
xxno = dcount(kept,am)
if xxno lt 1 then
crt 'Nothing in KEPT buffer'
return
end
bit = len(xxno)
disp = '***** Contents of KEPT buffer (':xxno:' lines) *****'
stub = 'Press return to continue showing KEPT buffer, Q to quit'
for xx = 1 to xxno
temp = oconv(kept<xx>,'MCP')[1,wide-bit-1]
disp<-1> = fmt(xx,'R#':bit):':':temp
next xx
gosub show.disp
case 1 ; gosub bad.command
end case
return
l: begin case
case index('\L\LN\LA\LNA\LAN\','\':comd:'\',1) ; * list or locate
if upcase(comi) eq 'L' then
if look<1,1> eq '' then
crt 'No previous locate command to repeat.'
comi = ''
return
end
comi = look<1,1>
gosub parse.command
if comd eq '' then comd = 'L' ; numb = huge
redo = true
return
end
finder = ''
seeker = dlim
if seeker eq '!' or seeker eq '&' then
finder = rest
convert dlim to am in finder
if finder<2> eq '' then finder = '' else rest = finder<1>
end
looper = dcount(finder,am)
if rest ne '' then
gosub parse.cols
if not(good) then return
end else
if dlim ne '' then
crt 'The second field is empty.'
gosub bad.comd ; return
end
cols = ''
end
if index(comd,'A',1) then
bump = -1
dawn = here - 1
if dawn lt 1 then dawn = 1
if numb then dusk = here - numb + 1 else dusk = 1
if dusk lt 1 then dusk = 1
end else
bump = 1
dawn = here + 1
if dawn gt last then dawn = 1
if numb then dusk = dawn + numb - 1 else dusk = last
if dusk gt last then dusk = last
end
if looper then rest = finder else looper = 1
line = rest ; gosub parse.line ; rest = line
lastfind = rest<1>
if not(caseflag) then rest = upcase(rest)
if spaceflag else convert ' ':char(9) to '' in rest
for here = dawn to dusk step bump
gosub get.line
if cols then line = line[cols,colf]
if caseflag then temp = line else temp = upcase(line)
if spaceflag else convert ' ':char(9) to '' in temp
badder = false ; gooder = false
for xx = 1 to looper
if index(temp,rest<xx>,1)
then gooder = true
else badder = true
next xx
if seeker eq '&' then gooder = not(badder)
if gooder then
if not(index(comd,'N',1)) then
gosub display.line
if not(numb) then exit
end
end else
if index(comd,'N',1) then
gosub display.line
if not(numb) then exit
end
end
next here
if numb then here = dusk
crt 'Now at line ':here:
if here eq last then crt ' (bottom)':
crt '.'
if rest ne '' and comi ne '' and comi ne look<1,1> then
look = insert(look,1,1,0,comi)
look = field(look,vm,1,looknumb)
end
case comd eq 'LC' ; * lower case (make line in)
if viewflag then gosub viewonly ; return
if rest eq '' then ccom = 'MCL' else ccom = 'QMCL'
gosub conv.command
* Various forms for loading stuff
case comd eq 'LD' or comd eq 'LOAD' or comd eq 'LDA' or comd eq 'LOADA'
if viewflag then gosub viewonly ; return
if not(sec.load.flg) then
crt 'LOAD disabled'
comi = ''
return
end
gosub get.load
if temp eq '' then return
if prepflag then
sec.call2.type = 1
sec.fn2 = ofpt
sec.id2 = oipt
sec.dict2.flg = (odpt = 'DICT')
call @prepprog(mat security)
if sec.stop.flg then stop
if not(sec.ok2.flg) then
gosub bad.comd ; return
end
end
if comd[len(comd),1] ne 'A' then
gosub get.lines
if not(temp) then return
end
gosub savethat
this = insert(this,here+1,0,0,temp)
temp = dcount(temp,am)
here = here + temp
crt 'At line ':here:', ':temp:' lines loaded.'
temp = ''
gosub set.record
case comd eq 'LL' ; * long lines
if not(rest matches '1N0N') then
rest = span-llen-2
crt 'LL':numb:'/':rest
end
dawn = here + 1
if dawn gt last then dawn = 1
if numb then dusk = here + numb else dusk = last
if dusk gt last then dusk = last
for here = dawn to dusk
gosub get.line
temp = trim(line[rest,huge])
if temp ne '' then
gosub display.line
if not(numb) then return
end
next here
crt
gosub display.line
case 1 ; gosub bad.command
end case
return
m: begin case
case comd eq 'M' ; * pattern matching
rest = field(rest,dlim,1)
if rest eq '' and mmat ne '' then
dlim = mmat<1,1>
rest = mmat<1,2>
end
if rest eq '' then
crt 'No pattern given to match'
return
end
gosub changematch.command
case comd eq 'MACRO'
if macn then
temp = dcount(macc<1,1>,sm)
macc = delete(macc,1,1,temp)
macc = delete(macc,1,1,temp)
if macc ne '' then
pres<1,macn> = macc<1,1>
crt 'Macro saved to PRestore ':macn
end else
crt 'Macro empty - not saved'
end
macc = ''
macn = 0
end else
if numb eq '' then numb = 1
if numb gt presnumb or numb lt 1 then
crt 'PRestore must be in range 1-':presnumb:'.'
comi = ''
return
end
crt 'Macro being recorded for PRestore ':numb
macn = numb
end
case comd eq 'MERGE' or comd eq 'ME' ; * merge stuff
if viewflag then gosub viewonly ; return
if rest eq '' and numb eq '' then
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd
return
end
numb = fin - beg + 1
if blockflag then
if beg eq fin
then stub = 'Copy line ':beg:' to under line ':here:'? '
else stub = 'Copy lines ':beg:'-':fin:' to under line ':here:'? '
gosub get.answ
if answ ne yes[1,1] then
crt 'Block command cancelled.'
return
end
end
dlim = ' '
rest = beg:' ':fin
numb = ''
end
rest = trim(rest)
if numb eq '' then gosub parse.atts
if numb ne '' and rest eq '' then rest = here
if not(rest matches '1N0N') or numb eq '' then
crt 'Format of MErge command is: "MEn/s"; eg: "ME10/15" or "ME/s/f"; eg: "ME/15/24"'
gosub bad.comd ; return
end
* if numb gt last then
* crt 'Nothing done - record does not have that many lines.'
* comi = '' ; return
* end
bite = field(this,am,rest,numb)
if numb ne 1 or bite ne '' then numb = dcount(bite,am)
if numb then
gosub savethat
this = insert(this,here+1,0,0,bite)
gosub set.record
if beg gt here then beg = beg + numb
if fin gt here then fin = fin + numb
xxno = dcount(krj<1>,vm)
for xx = 1 to xxno
if krj<2,xx> gt here then krj<2,xx> += numb
next xx
crt 'Merged ':numb:' lines starting at line ':rest:'; still at line ':here:'.'
end else
crt 'Nothing done - this line is within the range.'
comi = '' ; return
end
case comd eq 'MOVE' or comd eq 'MV' ; * move stuff
if viewflag then gosub viewonly ; return
if rest eq '' then
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd
return
end
if here le fin and here ge beg then
crt 'A block may not be moved into itself. MERGE will work.'
comi = ''
return
end
numb = fin - beg + 1
if blockflag then
if beg eq fin then
stub = 'Move line ':beg:' to after line ':here:' OK? ':ny
end else
stub = 'Move lines ':beg:'-':fin:' to after line ':here:' OK? ':ny
end
gosub get.answ
if answ ne yes[1,1] then
crt 'Block command cancelled.'
return
end
end
dlim = ' '
rest = beg:' ':fin
numb = ''
end
rest = trim(rest)
if numb eq '' then gosub parse.atts
if not(rest matches '1N0N') or numb eq '' then
crt 'Format of MoVe command is: "MVn/s"; eg: "MV10/15" or "MV/s/f"; eg: "MV/15/24"'
gosub bad.comd ; return
end
dusk = rest + numb - 1
if dusk gt last then dusk = last
if here ge rest and here le dusk then
crt 'Nothing done - this line is within the range.'
comi = '' ; return
end
bite = field(this,am,rest,numb)
numb = dcount(bite,am)
if numb then
gosub savethat
if here gt dusk then
this = insert(this,here+1,0,0,bite)
if rest gt 1
then this = this[1,col1()-1]:this[col2(),len(this)]
else this = this[col2()+1,len(this)]
end else
this = this[1,col1()-1]:this[col2(),len(this)]
this = insert(this,here+1,0,0,bite)
end
gosub set.record
if here gt dusk then
here = here - numb
crt 'Moved ':numb:' lines starting at line ':rest:'; now at line ':here:'.'
end else
crt 'Moved ':numb:' lines starting at line ':rest:'; still at line ':here:'.'
end
!##############
posn = beg; gosub recalc.posn; beg = posn
posn = fin; gosub recalc.posn; fin = posn
xxno = dcount(krj<1>,vm)
for xx = 1 to xxno
posn = krj<2,xx>; gosub recalc.posn; krj<2,xx> = posn
next xx
end else
crt 'Nothing done - no lines selected.'
comi = '' ; return
end
case 1 ; gosub bad.command
end case
return
n: begin case
case comd eq 'N' ; * same as "+"
if numb eq '' then numb = 1
here = here + numb
if here gt last then here = last
gosub display.line
case comd eq 'NULL' ; * null line input definition
dlim = trim(dlim):trim(rest)
dlim = dlim[1,1]
nill = dlim
if nill eq '"' then
bit = "'":nill:"'"
end else bit = '"':nill:'"'
crt 'NULL character to terminate INSERT is ':bit:'.'
comi = ''
case comd eq 'NUM' ; * toggle the line numbering
if lfmt eq '' then
crt 'Line Numbering is ON'
gosub get.lfmt
end else
crt 'Line Numbering is OFF'
lfmt = ''
end
case 1 ; gosub bad.command
end case
return
o: begin case
case comd eq 'OC' ; * oconv
if viewflag then gosub viewonly ; return
if rest eq '' then
crt 'No conversion given'
gosub bad.comd ; return
end
ccom = rest ; gosub conv.command
case comd[1,2] eq 'OO' ; * undo last change
if oopc ne '' then
this = oops
here = oopl
last = oopf
beg = oopb<1>
fin = oopb<2>
krj = oopk
gosub set.record
crt '"':oopc:'" undone - now at line ':here:'.'
oops = '' ; oopc = '' ; oopl = '' ; oopf = ''
oopb = '' ; oopk = ''
gosub display.line
end else
crt 'last change already "undone" or nothing to undo'
end
comi = ''
case comd eq 'OUT'
gosub outline
case 1 ; gosub bad.command
end case
return
p: begin case
case comd eq 'P' ; * page on
if numb else numb = plen
if here ge last then here = 0
here += 1
gosub set.bounds
for here = dawn to dusk
gosub display.line
next here
here = dusk
case comd eq 'PA' ; * print window up to here
if numb else numb = pwin
save = here
here = here - numb
gosub set.bounds
for here = dawn to dusk
gosub display.line
next here
here = save
crt 'Still at line ':here:'.'
case comd = 'PASTE' and rest eq '' ; * paste from kept
if viewflag then gosub viewonly ; return
if kept eq '' then
crt 'Nothing in KEPT buffer'
comi = '' ; return
end
gosub savethat
numb = dcount(kept,am)
this = insert(this,here+1,0,0,kept)
gosub set.record
crt 'Pasted ':numb:' lines from KEPT buffer; still at line ':here:'.'
if beg gt here then beg += numb
if fin gt here then fin += numb
xxno = dcount(krj<1>,vm)
for xx = 1 to xxno
if krj<2,xx> gt here then krj<2,xx> += numb
next xx
case comd eq 'PASTE' ; * save the kept buffer
if viewflag then gosub viewonly ; return
if kept eq '' then
crt 'Nothing in KEPT buffer'
comi = '' ; return
end
gosub save.stuff
case comd eq 'PE' ; * page editor mode
if not(editpage) then
crt 'Page editing not possible at this terminal'
comi = ''
return
end
that = this ; savl = here:am:last
if this eq '' then this = am
if here lt 1 then here = 1
ptop = here
mode = 'PAGE':am:'View'
if sec.write.flg then mode<2> = 'Ins'
pchr = 1
chng = '' ; show = ''
gosub display.page
*>
gosub get.line
*>
temp = line
case comd eq 'PL' ; * print window from here
if numb else numb = pwin
save = here
gosub set.bounds
for here = dawn to dusk
gosub display.line
next here
here = save
crt 'Still at line ':here:'.'
case comd eq 'PP' ; * print window bracketing here
if numb else numb = pwin
save = here
here = here - int(numb/2)
gosub set.bounds
for here = dawn to dusk
gosub display.line
next here
here = save
crt 'Still at line ':here:'.'
case comd eq 'PR' ; * prestore processing
if numb eq '' then
crt 'Defined prestores (':presnumb:' Maximum)'
for xx = 1 to presnumb
temp = pres<1,xx>
convert sm to comdmark in temp
$ifdef unidata
crt fmt(xx,'2/0R'):' ':temp
$else
crt fmt(xx,'R%2'):' ':temp
$endif
next xx
return
end
if numb gt presnumb or numb lt 1 then
crt 'PRestore must be in range 1-':presnumb:'.'
comi = ''
return
end
if dlim ne '' then
if not(rest eq rest<1,1,1>) then
crt 'Invalid - delimiter in prestore'
comi = ''
return
end
pres<1,numb> = change(rest,dlim,sm)
end else
salt = pres<1,numb>
end
case 1 ; gosub bad.command
end case
return
q: begin case
* Various forms for quitting
case comd eq 'Q' or comd = 'QK' or comd = 'QUIT' or comd = 'QUITK'
if not(viewflag) and (orig ne this) then
stub = '***** Record changed --- OK to Quit? (N/Y)>'
gosub get.answ
if answ eq yes[1,1] then stopsign = true
end else stopsign = true
if stopsign then
if orig eq '' then
crt 'Quit "':item:'" in file "':fnam:'" not created.'
end else crt 'Quit "':item:'" in file "':fnam:'" unchanged.'
if index(comd,'K',1) then
killsign = true
if idcnt gt 1 then crt 'Select list cancelled.'
end
end
case 1 ; gosub bad.command
end case
return
r: begin case
case comd eq 'RA' ; * view or repeat change
if viewflag then gosub viewonly ; return
gosub change.command
case comd eq 'R' and dlim ne '' and index(rest,dlim,1) ; * change
if viewflag then gosub viewonly ; return
crt ; comd = 'C'
gosub change.command
case comd eq 'R' ; * replace lines
if viewflag then crt ; gosub viewonly ; return
if not(last) then
crt 'Empty record, use Insert (I) command.'
comi = ''
return
end
if here lt 1 then here = 1 ; gosub display.line
chng = 0 ; save = here ; savl = last
if numb lt 1 then numb = 1
if dlim ne '' and rest eq '' then rest = ' '
loop
crt begn:
if lfmt then crt fmt(here,lfmt):'=':
crt ceop:
if rest eq '' then
stub = here:'='
if lfmt then stub = fmt(here,lfmt):'='
gosub get.rope; line = rope
end else line = rest
gosub parse.line
until line eq '' do
crt goup:begn:ceol:
if lfmt then crt fmt(here,lfmt):': ':
crt line
if line eq comdmark then
line = ''
crt begn:
if lfmt then crt fmt(here,lfmt):': ':
end
if numb gt 1 then crt
if line eq ' ' then line = ''
if not(chng) then gosub savethis
chng += 1
memr(cell)<lnum> = line
here += 1 ; numb -= 1
gosub get.line
if numb eq 0 then exit
repeat
if here ne save then here -= 1
if chng then gosub reset.record; gosub get.line
crt begn:ceol:
case comd eq 'RELEASE' ; * release the item lock
release file,item
lock = false
case 1 ; gosub bad.command
end case
return
s: begin case
case comd eq 'S' ; * search processing
if numb eq '' then
crt 'Last ':looknumb:' searches (latest first)'
for xx = 1 to looknumb
$ifdef unidata
crt fmt(xx,'2/0R'):' ':look<1,xx>
$else
crt fmt(xx,'R%2'):' ':look<1,xx>
$endif
next xx
return
end
if numb gt looknumb or numb lt 1 then
crt 'Search must be in range 1-':looknumb:'.'
comi = ''
return
end
comi = look<1,numb>
if comi eq '' then
crt 'There is no search number ':numb:'.'
return
end
look = delete(look,1,numb,0)
look = insert(look,1,1,0,comi)
gosub parse.command
if comd eq '' then comd = 'L' ; numb = huge
comi = ''
redo = true
case comd eq 'SAVE' or comd eq 'SV' ; * save the item
if viewflag then gosub viewonly ; return
comd = 'SV'
if rest eq '' then
if not(sec.write.flg) then
crt 'File disabled'
comi = ''
return
end
gosub write.record
end else gosub save.stuff
case comd eq 'SEQ' ; * build a sequence
if viewflag then gosub viewonly ; return
if dlim eq '' then
crt 'Too few fields in this command.'
gosub bad.comd ; return
end
good = true
cfrom = field(rest,dlim,1)
cto = field(rest,dlim,2)
if cto eq '' then cto = 1
if not(num(cto)) then
crt 'Base for sequence command must be a number.'
good = false
end
bit = field(rest,dlim,3)
if bit eq '' then bit = 1
if not(num(bit)) then
crt 'Increment for sequence command must be a number.'
good = false
end else
if not(bit) then
crt 'Increment for sequence command must not be zero.'
good = false
end
end
if not(good) then gosub bad.comd ; return
rest = dlim:field(rest,dlim,4,2)
if rest ne dlim then
gosub parse.cols
if not(good) then return
end else cols = ''
chng = 0 ; save = here ; savl = last
gosub set.bounds
for here = dawn to dusk
gosub get.line ; temp = line
if cols then
bite = index(line[cols,colf],cfrom,1)
if bite then bite = bite + cols - 1
end else
bite = index(line,cfrom,1)
end
if bite then
temp = line[1,bite-1]:cto
temp = temp:line[bite+len(cfrom),len(line)]
end
if '*':temp ne '*':line then
cto = cto + bit
if not(chng) then gosub savethis
chng += 1
memr(cell)<lnum> = temp
gosub display.line
end
next here
here = dusk
if chng then gosub reset.record
case comd eq 'SHOW' ; * show changes flag
rest = upcase(rest)
begin case
case rest eq 'ON' ; shew = true
case rest eq 'OFF' ; shew = false
case 1 ; shew = not(shew)
end case
if shew
then crt 'Show changes flag is ON'
else crt 'Show changes flag is OFF'
case comd eq 'SORT' or comd eq 'SORTU' ; * sort the block
if viewflag then gosub viewonly ; return
test = index(comd,'U',1)
if not(beg) and not(fin) then
crt 'Command requests a block operation, but no block is defined.'
gosub bad.comd
return
end
if beg le 1 then
temp = 0
end else
temp = index(this,am,beg-1)
if not(temp) then
crt 'Cannot find beginning of block'
gosub bad.comd ; return
end
end
rest = upcase(rest)
if rest eq '' then rest = 'AL'
if not(index('*AR*AL*DR*DL*','*':rest:'*',1)) then
crt 'Invalid sort sequence - use "AL" "AR" "DL" or "DR"'
gosub bad.comd ; return
end
temp<2> = index(this,am,fin)
if fin eq last then temp<2> = len(this)+1
if not(temp<2>) then
crt 'Cannot find end of block'
gosub bad.comd ; return
end
if blockflag then
stub = 'Sort block beginning at ': beg:' and ending at ': fin:'?'
gosub get.answ
if answ ne yes[1,1] then
crt 'Block command cancelled.'
return
end
end
gosub savethat
bits = ''
for here = beg to fin
gosub get.line
locate(line,bits;posn;rest) then
if test then good = false else good = true
end else good = true
if good then bits = insert(bits,posn;line)
next here
here = oopl
if fin ne last
then this = this[1,temp<1>]:bits:am:this[temp<2>+1,len(this)]
else this = this[1,temp<1>]:bits
bits = ''
gosub set.record
* If any tags are in the sorted block then clear the tags,
* as it really makes no sense to try and sort them.
good = true
xxno = dcount(krj<1>,vm)
for xx = 1 to xxno
posn = krj<2,xx>
if posn ge beg and posn le fin then good = false
next xx
if not(good) then
krj = ''
crt 'Tags cleared'
end
gosub display.line
case comd eq 'SPACE' ; * change spacing flag for 'L'
rest = upcase(rest)
begin case
case rest eq 'ON' ; spaceflag = true
case rest eq 'OFF' ; spaceflag = false
case 1 ; spaceflag = not(spaceflag)
end case
if spaceflag then
crt 'SPACE flag is ON'
end else crt 'SPACE flag is OFF'
case comd eq 'SPOOL' ; * print
save = here
if numb eq '' and rest matches '1N0N' then numb = rest
if numb eq '' then here = 1 ; numb = last
gosub set.bounds
head = 'Record - ':item:' File - ':fnam:' Account - ':acct:' '
head = head:timedate():"'LL'"
temp = span
printer on
temp = temp - llen - 2
heading head
for here = dawn to dusk
gosub get.line
convert badc to gudc in line
print fmt(here,lfmt):': ':line[1,temp]
loop
line = line[temp+1,len(line)]
until line eq '' do
print space(llen+2):line[1,temp]
repeat
next here
printer close
if dawn ne 1 or dusk ne last then
crt 'Lines ':dawn:' to ':dusk:' of ':
end
crt '"':item:'" spooled to the printer.'
here = save
case comd eq 'SPOOLHELP' ; * print the help
rest = am
gosub show.help
case comd eq 'STAMP' ; * stamp it
if viewflag then gosub viewonly ; return
gosub savethat
last += 1 ; here += 1 ; lnum += 1
line = '* Last updated by ':name:' in account ':acct:' at ':timedate()
gosub insert.line
gosub reset.record
gosub display.line
case 1 ; gosub bad.command
end case
return
t: begin case
case comd eq 'T' ; * top
here = 0
gosub display.line
case comd eq 'TC' ; * text case (make line in)
if viewflag then gosub viewonly ; return
if rest eq '' then ccom = 'MCT' else ccom = 'QMCT'
gosub conv.command
* Various ways to TRIM the line
case comd eq 'TRIM' or comd = 'TRIMF' or comd = 'TRIMB'
if viewflag then gosub viewonly ; return
chng = 0 ; save = here ; savl = last
if rest and comd eq 'TRIM' then
seek = field(rest,dlim,1)
if seek matches '3n' then seek = char(seek)
mark = field(rest,dlim,2)
mark = upcase(trim(mark))[1,1]
if index('ABCDEFLRT',mark,1) else
crt 'Invalid TRIM argument - must be one of "ABCDEFLRT"'
gosub bad.comd
return
end
end else seek = ''
show = shew ; dnum = 1
if numb eq '' and rest matches '1N0N' then numb = rest
gosub set.bounds
for here = dawn to dusk
gosub get.line
begin case
case comd eq 'TRIM'
if seek eq ''
then temp = trim(line)
else temp = trim(line,seek,mark)
case comd eq 'TRIMF' ; temp = trimf(line)
case comd eq 'TRIMB' ; temp = trimb(line)
end case
gosub check.line
next here
here = dusk
if chng then
gosub reset.record
crt chng:' lines changed - now at ':here
end
case comd eq 'TWIN' or comd eq 'TRIPLE' ; * sideways cloning of line
if viewflag then gosub viewonly ; return
if dlim ne '' then
line = rest ; gosub parse.line ; join = line
end
if here and here le last else return
chng = 0 ; save = here
gosub set.bounds
for here = dawn to dusk
gosub get.line
if comd eq 'TWIN'
then test = line:join:line
else test = line:join:line:join:line
if test ne line then
chng += 1
memr(cell)<lnum> = test
end
next here
if chng eq 0 then return
temp = 'Split ':chng:' lines'
if join ne '' then temp := ' and joined the parts with "':join:'"'
crt temp
here = save
gosub savethat
gosub reset.record
gosub display.line
case 1 ; gosub bad.command
end case
return
u: begin case
case comd eq 'U' ; * same as "-"
if numb eq '' then numb = 1
here = here - numb
if here lt 0 then here = 0
if here gt last then here = last
gosub display.line
case comd eq 'UC' ; * upper case (make line in)
if viewflag then gosub viewonly ; return
if rest eq '' then ccom = 'MCU' else ccom = 'QMCU'
gosub conv.command
case comd eq 'UNLOAD' ; comd = 'SV' ; redo = true
if viewflag then gosub viewonly ; return
case 1 ; gosub bad.command
end case
return
v: begin case
case comd eq 'V' ; * version information
crt (upcase(verb):' = ') 'R#20':help.def
$ifdef qm
temp = trans('NEWVOC','$RELEASE',2,'X')
if temp eq '' then
temp = trans('VOC','$RELEASE',2,'X')
end
if temp eq '' then temp = '?'
crt ('QM = ') 'R#20':temp
*>
crt ('Licence = ') 'R#20':system(31)
*>
$endif
$ifdef unidata
crt ' UniData version ':oconv('version','TVOC;X;;1')
$endif
$ifdef universe
temp = oconv('RELLEVEL','TNEWACC;X;;2')
if temp eq '' then
temp = oconv('RELLEVEL','TVOC;X;;2')
end
if temp eq '' then temp = 'not known'
crt ' UniVerse version ':temp
case comd eq 'VLIST'
execute comi capturing disp
stub = "Press return to continue showing VLIST 'T'op '-'back 'Q'uit"
gosub show.disp
$endif
case 1 ; gosub bad.command
end case
return
w: begin case
case comd eq 'W' or comd eq 'WHERE' ; * what we are editing
crt
if viewflag
then crt 'Viewing "':item:'" in file "':fnam:'"'
else crt 'Editing "':item:'" in file "':fnam:'"'
if idcnt gt 1 then crt ' [':id:'/':idcnt:']':
crt
if here gt last then here = last
gosub display.line
case comd eq 'WM' ; * word marker display (change)
if dlim ne '' then wordmark = dlim
if wordmark eq '"'
then crt 'WordMark is ':"'":wordmark:"'"
else crt 'WordMark is ':'"':wordmark:'"'
case 1 ; gosub bad.command
end case
return
x: begin case
* Another way of quitting
case comd eq 'X' ; comd = 'QK' ; redo = true
case comd eq 'XEQ' ; * execute a command
if viewflag then gosub viewonly ; return
if not(sec.xeq.flg) then
crt 'XEQ disabled'
comi = ''
return
end
loop
if rest ne '' then execute rest
test = @(0,0)
stub = '<RETURN> or command :'
gosub get.rope; rest = rope
if rest eq '' then
crt; crt 'Returned - ':
crt 'Editing "':item:'" in file "':fnam:'"'
end
until rest eq '' do
*>
crt
*>
repeat
gosub display.line
case comd eq 'XTD' ; * hex to decimal
$ifdef universe
crt xtd(rest)
$else
crt iconv(rest,'MX')
$endif
case 1 ; gosub bad.command
end case
return
y: begin case
case 1 ; gosub bad.command
end case
return
z: begin case
case 1 ; gosub bad.command
end case
return
set.bounds:
if numb eq '' then numb = 1
dawn = here
if dawn lt 1 then dawn = 1
dusk = dawn + numb - 1
if dusk gt last then dusk = last
numb = 0
return
null.command:
if dlim eq ':' then comd = 'XEQ' ; return
if dlim eq '/' then
comd = 'L'
if numb eq '' then numb = huge
return
end
if dlim eq '-' or dlim eq '+' then
if rest eq '' then rest = 1
end
if numb ne '' then comd = numb ; return
if dlim eq '' and rest eq '' then
here += 1
if here gt last then here = 1
gosub display.line
return
end
crt
begin case
case dlim eq '+' and rest matches '1N0N'
here = here + rest
if here gt last then here = last
gosub display.line
case dlim eq '-' and rest matches '1N0N'
here = here - rest
if here lt 0 then here = 0
if here gt last then here = last
gosub display.line
case dlim eq '^'
wild = not(wild)
if wild
then crt 'Expansion of non-printing characters enabled'
else crt 'Expansion of non-printing characters disabled'
case dlim eq '='
crt 'UNIDATA prestore is not implemented - Use "PR"'
case dlim eq '.'
gosub dot.command
case dlim eq '$'
if not(sec.xcom.flg) then
crt '$ external commands disabled'
comi = ''
return
end
save = comi ; comi = rest
gosub parse.command
comi = save
comd = '$':comd
xcom = oconv(comd,'TAE_XCOMS;X;2;2')
begin case
case xcom eq ''
crt 'Record "':comd:'" does not exist in "AE_XCOMS".'
case xcom[len(xcom)-2,3] ne '_AE'
disp = ''
disp<-1> = "Line 2 of record '":rest:"' in file 'AE_XCOMS'"
disp<-1> = "contains '":xcom:"'."
disp<-1> = ''
disp<-1> = 'This line should contain the name of a Basic subroutine that'
disp<-1> = "has been written to implement the external command '":rest:"'."
disp<-1> = "The program name must end in '_AE'."
stub = 'Press RETURN to continue'
gosub show.disp
case 1
that = this ; savl = here:am:last:beg:am:fin:am:krj
save = comi:am:comd:am:item:am:fnam
comd = comd:' ':rest
call @xcom(mat junk)
item = save<3>
fnam = save<4>
if here lt 0 then here = 0
gosub set.record
if here gt last then here = last
comd = ''
if that ne this then
crt save<2>:' - CHANGES HAVE BEEN MADE'
oops = that ; oopc = save<1>
oopl = savl<1> ; oopf = savl<2>
oopb = savl<3>:am:savl<4> ; oopk = field(savl,am,5,3)
end
that = ''
end case
case comi eq '?'
disp = ' Login name = ':name:' (':term:', userno ':whom:')'
disp<-1> = ' Account = ':acct
if path ne '' then disp<-1> = ' VOC path = ':path
disp<-1> = ' Level = ':levl
disp<-1> = ' File name = ':fnam
disp<-1> = ' Record id = ':item
disp<-1> = ' Current line = ':here
disp<-1> = ' Lines = ':last
disp<-1> = ' Characters = ':len(this)
if chan ne '' then
disp<-1> = 'Last Change command = ':chan<1,1>
end
if cmat ne '' then
temp = 'CM':cmat<1,3>:cmat<1,1>:cmat<1,2>
disp<-1> = 'Last CMatch command = ':temp
end
if olda then
temp = 'A':olda<1,2>:olda<1,1>
disp<-1> = 'Last Append command = ':temp
end
if beg or fin then
disp<-1> = ' Block = ':beg:'-':fin
end
if comdmark eq '"' then
temp = "'":comdmark:"'"
end else temp = '"':comdmark:'"'
disp<-1> = 'Command Delimiter is ':temp:', '
if nill eq '"' then
temp = "'":nill:"'"
end else temp = '"':nill:'"'
disp := 'character to end inserting is ':temp:', '
if wordmark eq '"' then
temp = "'":wordmark:"'"
end else temp = '"':wordmark:'"'
disp := 'WordMark is ':temp
disp<-1> = 'Page: window for PA/PL/PP is ':pwin:', length for P is ':plen
if wild
then disp<-1> = 'Expansion of non-printing characters enabled'
else disp<-1> = 'Expansion of non-printing characters disabled'
if caseflag then
disp<-1> = 'CASE':' flag ON':', '
end else disp<-1> = 'CASE':' flag OFF':', '
if spaceflag then
disp := 'SPACE':' flag ON':', '
end else disp := 'SPACE':' flag OFF':', '
if shew then
disp := 'SHOW':' flag ON':', '
end else disp := 'SHOW':' flag OFF':', '
if blockflag then
disp := 'BLOCK':' flag ON'
end else disp := 'BLOCK':' flag OFF'
if oopc ne '' then
disp<-1> = 'OOPS will restore record prior to command: ':oopc
end else
disp<-1> = 'OOPS already executed, or no changes in effect.'
end
gosub show.disp
case comi[1,2] eq '<>' ; gosub botharr
case comi[1,1] eq '<' ; gosub leftarr
case comi[1,1] eq '>' ; gosub rightarr
case dlim eq '\' and rest[1,1] eq '\' ;* clear the tag pointers
krj = ''
crt 'Tags cleared'
case dlim eq '\' ;* set a tag pointer
locate(here,krj,2;posn) then
crt 'There is already a Tag on line ':here
return
end
if rest eq '' then rest = 'T':here
rest = upcase(rest)
locate(rest,krj,1;posn) then
crt 'There is already a Tag labelled ':rest
return
end
posn = krj<3>
krj<1> = field(krj<1>,vm,1,posn)
posn += 1
krj<1,posn> = rest
krj<2,posn> = here
krj<3> = posn
crt 'Setting Tag labelled ':rest:' at line ':here
case (dlim eq '[' or dlim eq ']') and (rest[1,1] eq '[' or rest[1,1] eq ']')
if krj<3> eq ''
then disp = 'No Tag found'
else disp = 'Tags at line-Labelled'
posn = krj<3>
xxno = dcount(krj<1>,vm)
for xx = 1 to xxno
disp<-1> = krj<2,xx> 'r#12'
if xx eq posn then disp := '>' else disp := ' '
disp := krj<1,xx>
next xx
convert badc to gudc in disp
gosub show.disp
case dlim eq '[' and rest eq ''
posn = krj<3>-1
if posn gt 0 then
comd = krj<2,posn>
krj<3> = posn
crt 'Moved to line ':comd:' labelled ':krj<1
end else comd = ''
if comd eq '' then crt 'No Tag found'
case dlim eq ']' and rest eq ''
posn = krj<3>+1
comd = krj<2,posn>
if comd eq '' then
crt 'No Tag found'
end else
krj<3> = posn
crt 'Moved to line ':comd:' labelled ':krj<1
end
case dlim eq '[' or dlim eq ']'
locate(upcase(rest),krj,1;posn) then comd = krj<2,posn> else comd = ''
if comd ne '' then
krj<3> = posn
crt 'Moved to line ':comd:' labelled ':krj<1
return
end else crt 'No Tag found'
case 1
gosub bad.command
end case
return
parse.cols:
good = true
cols = field(rest,dlim,2)
convert ',.' to '--' in cols
rest = field(rest,dlim,1)
colf = field(cols,'-',2)
cols = field(cols,'-',1)
if colf eq '' then colf = cols
if cols ne '' then
if not(cols matches '1N0N') or not(colf matches '1N0N') then
crt 'Column specifications must be positive whole numbers.'
gosub bad.comd
good = false
return
end
end
if colf lt cols then
crt 'Ending column # must exceed or equal starting column #.'
gosub bad.comd
good = false
return
end
colf = colf - cols + 1
return
parse.atts:
convert '-' to dlim in rest
if dlim eq '"' then temp = "'" else temp = '"'
temp = '1N0N':temp:dlim:temp:'1N0N'
if rest matches temp then
numb = field(rest,dlim,2) - field(rest,dlim,1) + 1
rest = field(rest,dlim,1)
end
return
change.command:
if comd eq 'RA' then
if numb eq '' then
crt 'Last ':channumb:' changes (latest first)'
for xx = 1 to channumb
$ifdef unidata
crt fmt(xx,'2/0R'):' ':chan<1,xx>
$else
crt fmt(xx,'R%2'):' ':chan<1,xx>
$endif
next xx
return
end
if numb gt channumb or numb lt 1 then
crt 'Change must be in range 1-':channumb:'.'
comi = ''
return
end
comi = chan<1,numb>
if comi eq '' then
crt 'There is no change number ':numb:'.'
return
end
chan = delete(chan,1,numb,0)
chan = insert(chan,1,1,0,comi)
gosub parse.command
comi = 'RA'
end
save = upcase(field(rest,dlim,3,2))
if save ne '' then rest = rest[1,col1()]
gosub get.fromto
temp = save
if comi eq '' then return
chng = 0 ; save = here ; savl = last
glob = index(temp,'G',1)
show = shew or index(temp,'S',1)
convert dlim:'GS' to '-' in temp
rest = dlim:temp
gosub parse.cols
if not(good) then return
if numb lt plen then show = true
dnum = 1
gosub set.bounds
for here = dawn to dusk
gosub get.line
gosub change.line
gosub check.line
next here
here = dusk
if comi ne '' and upcase(comi) ne 'RA' then
chan = insert(chan,1,1,0,comi)
chan = delete(chan,1,channumb,0)
end
if chng then
gosub reset.record
if not(show) and dnum gt plen then
crt chng:' lines changed - now at ':here
end
end
return
get.fromto:
if count(rest,dlim) gt 2 then
crt 'Too many delimiters (3 max.).'
comi = ''
return
end
line = field(rest,dlim,1)
gosub parse.line
cfrom = line
line = field(rest,dlim,2)
gosub parse.line
cto = line
if cto eq '' and count(rest,dlim) lt 2 then
crt 'Missing required TO field (for "CHANGE/FROM/TO").'
comi = ''
return
end
return
change.line:
if cfrom eq '' then
temp = cto:line
end else
if glob then
temp = change(line,cfrom,cto)
end else
temp = index(line,cfrom,1)
if temp then
temp = line[1,temp-1]:cto:line[temp+len(cfrom),len(line)]
end else temp = line
end
end
return
conv.command:
chng = 0 ; save = here ; savl = last
show = shew or index(rest,'S',1) or index(rest,'s',1)
dnum = 1
if numb lt plen then show = true
if numb eq '' and rest matches '1N0N' then numb = rest
gosub set.bounds
ctyp = ccom[1,1]
begin case
* ICONV
case ctyp eq '*' ; ccom = ccom[2,huge]
* Text conversion LC, TC, or UC command
case ctyp eq 'Q' ; ccom = ccom[2,huge]
end case
for here = dawn to dusk
gosub get.line
begin case
case ctyp eq '*'
temp = iconv(line,ccom)
case ctyp eq 'Q'
temp = field(trim(line),' ',1)
flag = false
if temp ne 'REMOVE' then
if temp[1,3] eq 'REM' then flag = true
if temp[1,1] eq '*' then flag = true
if temp[1,1] eq '!' then flag = true
end
if flag then
temp = line
end else
xxno = len(line)
temp = ''
flag = ''
for xx = 1 to xxno
bit = line[xx,1]
begin case
case bit eq flag ; flag = ''
case flag ne ''
case index(qt,bit,1) ; flag = bit
*>
case bit eq ';'
test = trim(line[xx+1,huge])[1,1]
if test eq '*' or test eq '!' then flag = am
*>
case 1 ; bit = oconv(bit,ccom)
end case
temp = temp:bit
next xx
end
case 1
temp = oconv(line,ccom)
end case
if temp eq '' then temp = line
gosub check.line
next here
here = dusk
if chng then
gosub reset.record
if not(show) and dnum gt plen then
crt chng:' lines changed - now at ':here
end
end
return
dot.command:
if trim(comi) eq '.' then comi = '.L1'
save = comi
comi = field(comi,dlim,2,huge)
gosub parse.command
begin case
case comd eq 'A' ; * append to line
if numb eq '' then numb = 1
if numb gt dcount(stak,vm) then
crt 'History command ':numb:' does not exist.'
end else
stak<1,numb> := rest
$ifdef unidata
crt fmt(numb,'3/0R'):'. ':stak<1,numb>
$else
crt fmt(numb,'R%3'):'. ':stak<1,numb>
$endif
end
case comd eq 'C' ; * change lines
if numb eq '' then numb = 1
if numb gt dcount(stak,vm) then
crt 'History command ':numb:' does not exist.'
end else
gosub get.fromto
if comi eq '' then comd = '' ; return
glob = index(field(rest,dlim,3),'G',1)
glob = glob + index(field(rest,dlim,3),'g',1)
line = stak<1,numb>
gosub change.line
stak<1,numb> = temp
$ifdef unidata
crt fmt(numb,'3/0R'):'. ':temp
$else
crt fmt(numb,'R%3'):'. ':temp
$endif
end
case comd eq 'D' ; * delete lines
if numb eq '' then numb = 1
if numb gt dcount(stak,vm) then
crt 'History command ':numb:' does not exist.'
end else
stak = delete(stak,1,numb,0)
crt 'History #':numb:' DELETEd.'
end
case comd eq 'I' ; * insert a new line
if numb eq '' then numb = 1
if numb gt dcount(stak,vm) then
crt 'History command ':numb:' does not exist.'
end else
if rest ne '' then
stak = insert(stak,1,numb,0,rest)
stak = delete(stak,1,staknumb,0)
$ifdef unidata
crt fmt(numb,'3/0R'):'. ':stak<1,numb>
$else
crt fmt(numb,'R%3'):'. ':stak<1,numb>
$endif
end
end
case comd eq 'L' ; * list lines
if numb eq '' then numb = plen
if numb gt dcount(stak,vm) then numb = dcount(stak,vm)
temp = rem(numb+1,plen)
for xx = numb to 1 step -1
$ifdef unidata
crt fmt(xx,'3/0R'):'. ':stak<1,xx>
$else
crt fmt(xx,'R%3'):'. ':stak<1,xx>
$endif
if xx gt 1 and rem(xx,plen) eq temp then
stub = 'Press return to continue, Q to quit'
rlen = 1
gosub get.rope; crt begn:ceol:
wait = trim(upcase(rope))[1,1]
if wait eq 'Q' then exit
end
next xx
case comd eq 'R' ; * restore a line to latest
if numb eq '' then numb = 1
if numb le dcount(stak,vm) then
temp = stak<1,numb>
stak = insert(stak,1,1,0,temp)
stak = delete(stak,1,staknumb,0)
end
case comd eq 'S'
if numb eq '' then numb = 1
if numb gt presnumb then
crt numb:' is greater than pre-store limit of ':presnumb
return
end
rest = trim(rest)
dawn = field(rest,dlim,1) ; if dawn eq '' then dawn = 1
dusk = field(rest,dlim,2) ; if dusk eq '' then dusk = 1
if not(dawn matches '1N0N' and dusk matches '1N0N') then
crt 'One of the values was not a number'
return
end
if dawn gt dusk then temp = dawn ; dawn = dusk ; dusk = temp
temp = ''
for xx = dusk to dawn step -1
temp<1,1,-1> = stak<1,xx>
next xx
pres<1,numb> = temp
case comd eq 'U' ; * upcase line
if numb eq '' then numb = 1
if numb gt dcount(stak,vm)
then crt 'History command ':numb:' does not exist.'
else stak<1,numb> = upcase(stak<1,numb>)
case comd eq 'UL' ; * downcase line
if numb eq '' then numb = 1
if numb gt dcount(stak,vm)
then crt 'History command ':numb:' does not exist.'
else stak<1,numb> = downcase(stak<1,numb>)
case comd eq 'UT' ; * mixed case line
if numb eq '' then numb = 1
if numb gt dcount(stak,vm)
then crt 'History command ':numb:' does not exist.'
else stak<1,numb> = oconv(stak<1,numb>,'mct')
case comd eq 'X' ; * re-execute an editor command
if numb eq '' then numb = 1
if numb gt dcount(stak,vm) then
crt 'History command ':numb:' does not exist.'
end else
salt = stak<1,numb>
stak = delete(stak,1,numb,0)
end
case 1
comi = save
gosub bad.command
end case
comi = '' ; comd = ''
return
viewonly:
crt 'That command is not allowed in VIEW mode':bell
comi = ''
return
bad.command:
crt 'Command not understood - try "H" for help.'
bad.comd:
xxno = len(comi)
temp = ''
for xx = 1 to xxno
bite = comi[xx,1]
bite = seq(bite)
if bite ge 127 or bite lt 32 then
$ifdef unidata
bite = '^':fmt(bite,'3/0R')
$else
bite = '^':fmt(bite,'R%3')
$endif
end else bite = char(bite)
temp = temp:bite
next xx
crt 'Command was: "':temp:'"'
temp = ''
comi = ''
return
save.stuff:
if not(sec.unload.flg) then
crt 'Unload disabled'
comi = ''
return
end
keepquot = false
gosub parse.rest
odpt = '' ; ofpt = bite<1> ; oipt = bite<2>
onam = ofpt
if ofpt eq 'DICT' then
odpt = ofpt ; ofpt = oipt ; oipt = bite<3>
onam = onam:' ':ofpt
end
if oipt eq '' then
if odpt ne '' then
crt 'Cannot save to null item.'
gosub bad.comd ; return
end
oipt = ofpt ; odpt = dprt ; ofpt = fprt ; onam = fnam
end
if dprt eq odpt and fprt eq ofpt then
ofil = file
end else
open odpt, ofpt to ofil else
crt 'Cannot open ':'"':fnam:'"'
gosub bad.comd ; return
end
end
if prepflag then
sec.call2.type = 2
sec.fn2 = ofpt
sec.id2 = oipt
sec.dict2.flg = (odpt = 'DICT')
call @prepprog(mat security)
if sec.stop.flg then stop
if not(sec.ok2.flg) then
gosub bad.comd ; return
end
end
if source.control then
dict.flag = odpt
file.name = ofpt
record.name = oipt
record.data = this
caller = '3'
write.allowed = '1'
updated = '0'
call source.control(dict.flag,file.name,
record.name,record.data,caller,write.allowed,updated)
if write.allowed ne '1' then
crt 'WRITE NOT ALLOWED'
return
end
end
readv test from ofil, oipt, 1 then
stub = 'Record already exists. Overwrite (y/n)? '
gosub get.answ
if answ ne yes[1,1] then return
end
if comd eq 'PASTE' then
write kept on ofil, oipt on error gosub writerr ; return
end else
write this on ofil, oipt on error gosub writerr ; return
end
crt 'Record "':oipt:'" saved in "':onam:'".'
return
write.record:
if rest ne '' then
if comd eq 'FD' then
crt '"FD" operates only on the current record & file.'
end else
crt '"FI" only for current record & file. Use SAVE.'
end
gosub bad.comd ; return
end
if source.control then
dict.flag = dprt
file.name = fprt
record.name = item
if comd eq 'FD' then record.data = '' else record.data = this
caller = '3'
write.allowed = '1'
updated = '0'
call source.control(dict.flag,file.name,
record.name,record.data,caller,write.allowed,updated)
if write.allowed ne '1' then
crt 'WRITE NOT ALLOWED'
return
end
end
if not(lock) then
crt 'Record lock has been released! Write not allowed.'
comi = ''
return
end
if comd eq 'FD' then
stub = '***** You are about to DELETE the record! OK? ':ny
gosub get.answ
if answ ne yes[1,1] then return
delete file, item on error gosub writerr ; return
crt 'Deleted "':item:'" from file "':fnam:'".'
end else
if comd eq 'SV' then
writeu this on file, item on error gosub writerr ; return
orig = this ; oops = '' ; oopc = '' ; oopl = '' ; oopf = ''
oopb = '' ; oopk = ''
crt 'Saved "':item:'" in "':fnam:'" - now at line ':here:'.'
return
end else
write this on file, item on error gosub writerr ; return
if orig eq this then
crt 'Filed "':item:'" in file "':fnam:'" UNCHANGED.'
end else crt 'Filed "':item:'" in file "':fnam:'".'
oops = '' ; oopc = '' ; oopl = '' ; oopf = '' ; * ewd
end
end
stopsign = true
if index(comd,'B',1) then
temp = 'BASIC'
$ifdef qm
if index(comd,'D',1) then temp<2> = ' DEBUGGING'
$endif
gosub exec.that
end
if index(comd,'C',1) then
temp = 'CATALOG'
begin case
case index(comd,'L',1) ; temp<2> = ' LOCAL'
* case index(comd,'G',1) ; temp<2> = ' GLOBAL'
end case
gosub exec.that
end
if index(comd,'R',1) then temp = 'RUN' ; gosub exec.that
return
edit.fields:
if here lt 1 then here = 1
gosub get.line ; temp = line
convert vmrk to am in line
ttid = whom:'_':levl:'_':vals:'.in.line#':here
write line on acom, ttid on error gosub writerr ; return
crt view:'ing ':vals:' as fields...':
execute verb:' AE_COMS ':ttid:options
test = @(0,0)
crt 'Back ':view:'ing the record "':item:'" in file "':fnam:'"'
read line from acom, ttid else line = ''
delete acom, ttid
return
reset.fields:
convert am to vmrk in line
if temp ne line then
gosub savethat
memr(cell)<lnum> = line
gosub reset.record
end
return
get.load:
temp = ''
if trim(rest) eq '' then
stub = 'Record name, or file name and record name >'
gosub get.rope; rest = rope; crt
if trim(rest) eq '' then temp = ''; return
end
keepquot = false
gosub parse.rest
onam = bite<1>
onid = bite<2>
if onam eq 'DICT' then
onam = onam:' ':onid
onid = bite<3>
if onid eq '' then onid = item
end
if onid eq '' then onid = onam ; onam = ''
if onid eq '' then return
if onam eq '' then
onam = fnam
odpt = dprt
ofpt = fprt
ofil = file
end else
odpt = field(onam,' ',1)
ofpt = field(onam,' ',2)
if ofpt eq '' then ofpt = odpt ; odpt = ''
open odpt, ofpt to ofil else
crt 'Cannot open ':onam
gosub bad.comd ; return
end
end
read temp from ofil, onid else
if dcount(bite,am) eq 1 then
open onid to ofil then
read temp from ofil, item then return
end
end
crt 'Record "':onid:'" was not found on file "':onam:'".'
gosub bad.comd ; return
end
return
changematch.command:
patt = field(rest,dlim,1)
gosub parse.pattern
if not(good) then
crt 'Pattern: character "':bit:'" is not allowed unless quoted.'
comi = ''
return
end
if comd eq 'CM' then cmat = dlim:vm:rest:vm:numb
cto = field(rest,dlim,3,huge)
line = cto ; gosub parse.line ; cto = line
cfrom = upcase(field(rest,dlim,2))
if cfrom eq '' then cfrom = 'L'
if cfrom eq 'L' then mmat = dlim:vm:rest
if numb eq '' and cto eq '' and (cfrom eq 'L' or cfrom eq 'N') then
numb = last
flag = true
end else flag = false
if len(cfrom) eq 1 and index('ADLNPR',cfrom,1) then
end else
gosub parse.cols
if not(good) then return
cfrom = ''
colf = cols + colf - 1
end
cm.del.entry:
gosub set.bounds
show = shew ; dnum = 1
chng = 0 ; save = here ; savl = last ; dnum = 2
test = ''
for here = dawn to dusk
gosub get.line
if cfrom eq 'DE'
then good = index(line,patt,1)
else good = (line matches patt)
if not(good) then
if cfrom eq 'N' then
numb += 1
if show or numb lt plen then gosub display.line
if flag then dusk = here
end
continue
end
numb += 1
temp = line
begin case
case cfrom eq 'A'
temp = line:cto
case cfrom[1,1] eq 'D'
if show or numb lt plen then crt fmt((here + chng),lfmt):'+ ':line
test<-1> = here
case cfrom eq 'L'
gosub display.line
if flag then dusk = here
case cfrom eq 'P'
temp = cto:line
case cfrom eq 'R'
temp = cto
case cfrom eq 'N'
numb -= 1
case 1
gosub parse.temp
end case
if not(index('DL',cfrom,1)) or cfrom eq '' then
gosub check.line
end
next here
if cfrom[1,1] eq 'D' and numb then
gosub savethis
for here = numb to 1 step -1
temp = test<here>
cell = int((temp-1)/cellsize) + 1
coff = rem(temp,cellsize)
if coff eq 0 then coff = cellsize
del memr(cell)<coff>
if beg eq temp then beg = 0
if beg gt temp then beg -= 1
if fin eq temp then fin = 0
if fin gt temp then fin -= 1
for xx = dcount(krj<1>,vm) to 1 step -1
begin case
case krj<2,xx> gt temp ; krj<2,xx> -= 1
case krj<2,xx> eq temp
del krj<1,xx> ; del krj<2,xx> ; krj<3> -= 1
end case
next xx
next here
test = ''
gosub reset.record
here = dusk - numb
end else
here = dusk
end
if dawn ne dusk then
if here lt last
then crt 'At line ':here:'.'
else crt 'Bottom at ':here:'.'
end
if not(numb) then
if cfrom eq 'N' then
crt 'No lines (in ':dawn:'-':dusk:') NOT matching pattern "':patt:'"'
end else crt 'No lines (in ':dawn:'-':dusk:') matching pattern "':patt:'"'
end else
begin case
case cfrom[1,1] eq 'D'
crt 'Deleted ':numb:' lines matching "':patt:'"'
case cfrom eq 'L'
crt 'Found ':numb:' lines matching "':patt:'"'
case cfrom eq 'N'
crt 'Found ':numb:' lines NOT matching "':patt:'"'
end case
end
if chng then
gosub reset.record
begin case
case dawn eq dusk
return
case cfrom eq 'A'
crt '"':cto:'" appended to ':
case cfrom[1,1] eq 'D'
crt 'Deleted ':
case cfrom eq 'P'
crt '"':cto:'" prefixed to ':
case cfrom eq 'R'
crt 'Replaced with "%", ':
case cfrom eq 'L' or cfrom eq 'N'
case cols eq colf
crt 'Element ':cols:' changed to "':cto:'" in ':
case cols
crt 'Element ':cols:'-':colf:' changed to "':cto:'" in ':
end case
if chng eq 1
then crt '1 line matching "':patt:'"'
else crt chng:' lines matching "':patt:'"'
end
return
parse.pattern:
* bits<1> are the pattern pieces
* <2> quote or 'p'attern flag
* <3> partial patterns
cntr = 1
bits = ''
flag = ''
good = true
first = true
xxno = len(patt)
gosub quote.pattern
for xx = 1 to xxno
bit = patt[xx,1]
begin case
case bit = flag
flag = ''
first = true
cntr = cntr + 1
case flag ne ''
bits<1,cntr> = bits<1,cntr>:bit
case index(qt,bit,1)
bits<2,cntr> = bit
flag = bit
case first
if not(bit matches '1n') then
good = false
return
end
first = false
bits<2,cntr> = 'p'
bits<1,cntr> = bits<1,cntr>:bit
if bit eq '0' then bits<3,cntr> = patt[xx+2,xxno]
case 1
if not(index('AaNnXx',bit,1)) then
good = false
return
end
bits<1,cntr> = bits<1,cntr>:oconv(bit,'mcu')
first = true
cntr = cntr + 1
end case
next xx
cntr = cntr - 1
return
quote.pattern:
* Adds quotes to the pattern if required
* If they use any quotes at all, we don't do a thing
if index(patt,'"',1) then return
if index(patt,'\',1) then return
if index(patt,"'",1) then return
xx = 1
temp = ''
test = ''
loop
left = patt[xx,2]:'*'
if index('0123456789',left[1,1],1) and index('AaNnXx',left[2,1],1) then
if test ne '' then temp := "'":test:"'"
temp := patt[xx,2]
test = ''
xx += 1
end else test := patt[xx,1]
until xx gt xxno do
xx += 1
repeat
patt = temp
if test ne '' then patt := "'":test:"'"
return
parse.temp:
temp = ''
posn = 1
xxno = len(line)
for xx = 1 to cntr
what = bits<1,xx>
type = bits<2,xx>
nmbr = what[1,1]
begin case
case xx gt colf
temp<xx> = line[posn,xxno]
xx = cntr
case type ne 'p'
temp<xx> = line[posn,len(what)]
posn = posn + len(what)
case xx = cntr
temp<xx> = line[posn,xxno]
case nmbr = '0'
* look to match the rest of the line with the partial pattern
test = bits<3,xx>
yy = posn
bit = ''
loop
until yy gt xxno do
chit = line[yy,xxno]
until chit matches test do
bit := chit[1,1]
yy += 1
repeat
posn += len(bit)
temp<xx> = bit
case 1
bit = line[posn,nmbr]
posn += len(bit)
temp<xx> = bit
end case
next xx
temp<cols> = cto
for xx = cols+1 to colf
temp = delete(temp,cols+1)
next xx
convert am to '' in temp
return
get.lines:
stub = '"Q"uit, or starting line > '
pick = 1
gosub get.rope; dawn = rope
dawn = upcase(trim(dawn))
if dawn eq '' then dawn = 'Q'
if dawn[1,1] eq 'Q' then temp = false ; crt ; return
if not(dawn matches '1N0N') then
crt
crt 'Nothing done - starting and ending lines must be numeric.'
gosub bad.comd ; return
end
if dawn gt dcount(temp,am) then
crt
crt 'Nothing done - record does not have that many lines.'
gosub bad.comd ; return
end
stub = stub:dawn:' ':', ending line > '
pick = dcount(temp,am)
gosub get.rope; dusk = rope
dusk = upcase(trim(dusk))
if dusk eq '' then dusk = 'Q'
if dusk[1,1] eq 'Q' then temp = false ; crt ; return
if not(dusk matches '1N0N') then
crt
crt 'Nothing done - starting and ending lines must be numeric.'
gosub bad.comd ; return
end
if dusk gt dcount(temp,am) then
dusk = dcount(temp,am)
crt begn:'File is ':onam:': "Q"uit, or starting line > ':dawn:', ':dusk:
end
temp = field(temp,am,dawn,dusk-dawn+1)
crt
return
parse.bite:
temp = ''
loop
while bite ne '' do
bite = trimf(bite)
xx = fold
if count(bite[1,xx],' ') and trim(bite[xx+1,1]) ne '' then
loop
until trim(bite[xx,1]) eq '' do
xx -=1
repeat
temp<-1> = bite[1,xx-1]
end else
temp<-1> = bite[1,xx]
end
bite = bite[xx+1,len(bite)]
repeat
return
show.help:
crt
if help eq '' then
help = ''
help<-1> = ' ':verb:' version ':help.def
help<-1> = ' This program can be called with the following formats:'
help<-1> = " ":verb:" file and record id's are prompted for"
help<-1> = " ":verb:" file record id's are prompted for"
help<-1> = " ":verb:" file id ":view:" the record 'id' in 'file'"
help<-1> = " ":verb:" file id id... ":view:" multiple records in 'file'"
help<-1> = " ":verb:" file * ":view:" all records in 'file'"
help<-1> = " SELECT may precede '":verb:" file' command"
help<-1> = ' Special ASCII characters may be entered as:'
help<-1> = ' ^nnn where nnn is the decimal character code (like ^027)'
help<-1> = ' ^ will enter a single UP ARROW character.'
help<-1> = ' The following commands may be used in the Editor:'
help<-1> = 'A# - Do the last Append command again for # lines.'
help<-1> = "A# any - Append 'any' to # lines (default 1)."
help<-1> = 'B + Set the current line pointer to the BOTTOM line.'
help<-1> = "B# any - BREAK # lines (default 1) after string 'any' into two lines."
help<-1> = 'BC# posn = Break Column - Break # lines (default 1) after posn into two.'
help<-1> = 'BCD# posn = Break Column and Discard the second part.'
help<-1> = 'BCK# posn = Break Column and Keep only the second part.'
help<-1> = 'BCR# posn = Break Column and Reverse the order of the two parts.'
help<-1> = 'BCS# posn = Break Column and Swap the parts about the character at posn.'
help<-1> = "BD# any - BREAK after string 'any' and Discard the second part."
help<-1> = "BK# any - BREAK after string 'any' and Keep only the second part."
help<-1> = "BR# any - BREAK after string 'any' and Reverse the order of the two parts."
help<-1> = "BS# any - BREAK after string 'any' and Swap the parts about 'any'."
help<-1> = 'BLEACH ON/OFF# Switch colourisation flag.'
help<-1> = 'BLOCK ON/OFF + Switch block operation confirmation flag.'
help<-1> = ' If neither ON nor OFF is used, then toggle BLOCK flag.'
help<-1> = "C - Do the last 'CHANGE' command again."
help<-1> = 'C/// - CHANGE one or more lines. Full formats is:'
help<-1> = ' C[#]/from/to/[G][S]'
help<-1> = ' where / - is any delimiter character.'
help<-1> = ' # - number of lines to CHANGE (default 1).'
help<-1> = ' from - is the character string to be replaced.'
help<-1> = ' to - is the character string to substitute.'
help<-1> = " G - 'G'lobal flag - CHANGE all instances in line."
help<-1> = " S - 'S'how flag - display all changes made."
help<-1> = 'CASE ON/OFF + Switch CASE flag for FL, FLA, L, LA, LN, LNA commands.'
help<-1> = ' If neither ON nor OFF is used, then toggle CASE flag.'
help<-1> = ' OFF means that the commands are not case sensitive.'
help<-1> = "CAT - Synonym for 'J'oin."
help<-1> = 'CD + Show or change the command delimiter.'
help<-1> = ' (this is the input for a blank line).'
help<-1> = 'CLEAR # Clear the kept buffer.'
help<-1> = 'CM/// - ChangeMatch one or more lines. Full formats is:'
help<-1> = ' CM[#]/pattern[/range/to]'
help<-1> = ' where / - is any delimiter character.'
help<-1> = ' # - number of lines to CHANGE (default 1).'
help<-1> = ' pattern - is the pattern match for the line.'
help<-1> = ' to - is the character string to substitute/add.'
help<-1> = ' range - Can be numeric, which field(s) to change,'
help<-1> = " or 'A'ppend or 'P'refix to the line,"
help<-1> = " or 'D'elete, 'R'eplace, 'L'ocate (default) the line."
help<-1> = " EG 'CM/6X' will scan to the line matching '6X'."
help<-1> = " Also; 'N'ot - locate the next non-matching line."
help<-1> = 'COL + Display relative COLUMN POSITIONS on the Terminal.'
help<-1> = 'COPY # Copy the predefined block to the kept buffer.'
help<-1> = 'COPY# # Copy the next # lines to the kept buffer.'
help<-1> = 'COPYx/y # Copy x lines starting at line y to the kept buffer.'
help<-1> = 'COPY/x/y # Copy lines from x to y inclusive to the kept buffer.'
help<-1> = "COUNT#/any + Count of 'any' in next # lines (default 1)."
help<-1> = "CRT xxxx - Inserts a line CRT 'xxxx = ':xxxx"
help<-1> = ' Use double quote or backslash as delimiter to change quotes.'
help<-1> = 'CUT = Move the predefined block to the kept buffer.'
help<-1> = 'CUT# = Move the next # lines to the kept buffer.'
help<-1> = 'CUTx/y = Move x lines starting at line y to kept buffer.'
help<-1> = 'CUT/x/y = Move lines from x to y inclusive to kept buffer.'
help<-1> = 'D + Display the current line.'
help<-1> = 'DE - DELETE the current line.'
help<-1> = "DE# - DELETE '#' lines (default 1)."
help<-1> = "DE#/any - DELETE as above, but only if the line contains 'any'."
help<-1> = "DISPLAY xxxx - Inserts a line DISPLAY 'xxxx = ':xxxx"
help<-1> = ' Just like CRT, handy to distinguish debug code.'
help<-1> = 'DROP - Remove the predefined block.'
help<-1> = "DTX any + Convert decimal string 'any' to hexadecimal and display it."
help<-1> = 'DUP - DUPLICATE the current line.'
help<-1> = "DUP# - DUPLICATE the current line '#' times."
help<-1> = 'EC + Edit a called subroutine in this file.'
help<-1> = 'ECS # Edit the command stack.'
help<-1> = 'EF# + Edit fields delimited by CHAR(#) as lines.'
help<-1> = 'EI + Edit the included code.'
help<-1> = 'EIT + Edit I-type (not just a split on semi-colon).'
help<-1> = 'EK # Edit the kept buffer.'
help<-1> = 'EPR + Edit the prestored commands.'
help<-1> = 'EPR# # Edit prestored commqnd #.'
help<-1> = 'ESS # Edit Search Stack.'
help<-1> = 'ESV + Edit subvalues as 1ines.'
help<-1> = 'ET # Edit the line tabs.'
help<-1> = 'EV + Edit multivalues as lines.'
help<-1> = 'EW + Edit words as lines.'
help<-1> = 'EXIT (EX) + QUIT - EXIT the program.'
help<-1> = 'EXITK (EXK) + QUITKill - EXIT the program, abandon any active SELECT list.'
help<-1> = 'FD - DELETE the entire record from the file.'
help<-1> = 'FI - FILE the record. You can also process it.'
help<-1> = ' FIB = BASIC, FIC = CATALOG, FIR = RUN'
help<-1> = ' You can have up to three processes (EG. FIBCR).'
help<-1> = ' You can modify BASIC with D for DEBUGGING (EG. FIBD).'
help<-1> = ' You can modify CATALOG with L for LOCAL (EG. FICL).'
help<-1> = 'FILE - Synonym for SAVE.'
help<-1> = 'FL + Find the next Label.'
help<-1> = "FL any + Find the label 'any' or matching pattern 'any'."
help<-1> = 'FL# + Find (display) the labels in next # lines.'
help<-1> = 'FLA + Find label above this line.'
help<-1> = 'FM + Find Matching logic by position.'
help<-1> = 'FMA + Find Matching logic by position above this line.'
help<-1> = 'FOLD/length - Split current line (on blanks if possible) to fit width.'
help<-1> = 'FORMAT (FOR) + FORMAT a BASIC program to show logical structure by'
help<-1> = ' indenting. This has the following keywords;'
help<-1> = " '-Mx' = Set margin to x."
help<-1> = " '-Iy' = Set Indentation to y."
help<-1> = " '-A' = Align comments with code."
help<-1> = " '-N' = No CASE indentation."
help<-1> = " '-C' = Compress - same as '-M0 -I1 -A -N'."
help<-1> = "G# + GO TO line '#' ('G' is optional)."
help<-1> = 'HELP (H) + Prompt user to display HELP information on the Terminal.'
help<-1> = "HELP any + Display HELP information on Terminal for 'any'."
help<-1> = 'HELP NEW + Display HELP information on new features.'
help<-1> = 'HEX + Displays the current line in hexadecimal.'
help<-1> = 'I - INSERT new lines AFTER the current line. Prompt for'
help<-1> = ' successive lines. INPUT until NULL input. An INPUT line'
help<-1> = ' of a single space will store an empty line.'
help<-1> = "I any - INSERT (INPUT) the line 'any' AFTER the current line."
help<-1> = "I#/any - INSERT # lines of 'any' AFTER the current line."
help<-1> = "IC any - IConv the line using the conversion 'any'."
help<-1> = 'IN command - Insert the results of the command AFTER the current line.'
help<-1> = ' It is not a good idea to use a command requiring input.'
help<-1> = "J#/any - Join next '#' lines (default 1), separated by 'any'."
help<-1> = "KEEP name # Copy the record 'name' into the kept buffer."
help<-1> = " line #'s will be prompted."
help<-1> = "KEEP f name # Copy the record 'name' from file 'f' into the kept buffer,"
help<-1> = " line #'s will be prompted."
help<-1> = 'KEEPA # KEEPAll - KEEP without line # prompting.'
help<-1> = 'KEPT (K) # Display the kept buffer.'
help<-1> = "L + Repeat the last 'LOCATE' command (L, LA, LN, or LNA)."
help<-1> = "L any + LOCATE the next line that contains the string 'any'."
help<-1> = "L#/any/10-20 + LOCATE in next # lines those with 'any' in columns 10 to 20."
help<-1> = " So 'L#' effectively lists # lines."
help<-1> = "L#!any!THING # LOCATE in next # lines those with 'any' OR 'THING'."
help<-1> = "L#&any&THING # LOCATE in next # lines those with 'any' AND 'THING'."
help<-1> = ' ! and & work this way for LA, LN, and LNA commands too.'
help<-1> = 'LA#/any/1-20 + Locate lines above this one (reverse order).'
help<-1> = "LC# - Change '#' lines to lower case (default 1)."
help<-1> = 'LC# any Comments and quoted strings are unchanged.'
help<-1> = "LL#/length + Show lines 'length' or longer (null '#' is a search)."
help<-1> = "LN#/any/1-20 + LOCATE NOT - line without 'any' in columns 10 to 20."
help<-1> = "LNA#/an/1-20 + LOCATE line above this without 'an' in columns 1 to 20."
help<-1> = "LOAD name - LOAD the record 'name' from the current FILE,"
help<-1> = " line #'s will be prompted."
help<-1> = "LOAD f name - LOAD the record 'name' from file 'f',"
help<-1> = " line #'s will be prompted."
help<-1> = 'LOADA - LOADAll - LOAD without line # prompting.'
help<-1> = 'LD - Synonym for LOAD.'
help<-1> = 'LDA - Synonym for LOADA.'
help<-1> = 'M pattern + Search for a line matching the pattern.'
help<-1> = 'MACRO# + Toggle macro recording into #th PRESTORE command.'
help<-1> = 'MERGE (ME) = Merge a copy of the predefined block after the current line.'
help<-1> = 'MERGEx/y = Merge x lines starting at line y.'
help<-1> = 'MERGE/x/y = Merge lines starting at x to line y inclusive.'
help<-1> = 'MOVE (MV) - Move the predefined block to after the current line.'
help<-1> = 'MOVEx/y = Move the x lines starting at line y.'
help<-1> = 'MOVE/x/y = Move the lines starting at x to line y inclusive.'
help<-1> = 'NUM + Toggle the line numbering.'
help<-1> = "NULL/symbol + Change the null line input for 'I' to 'symbol'."
help<-1> = "OC# any - OConv '#' lines using the conversion 'any'."
help<-1> = 'OOPS - RESTORE the record to the condition prior to last change.'
help<-1> = "OUT# # Outline (labels, gotos, gosubs) for '#' lines (default all)."
help<-1> = 'OUT# CEPS Show Calls, Executes, Performs, and caSe also (* for all).'
help<-1> = 'P + PRINT on Terminal one page worth of lines.'
help<-1> = "P# + PRINT on Terminal '#' lines starting with the current line."
help<-1> = "PA# + PRINT the current line and the prior '#' lines,"
help<-1> = ' do not change the current line pointer.'
help<-1> = "PASTE = Paste the kept buffer after the current line'."
help<-1> = "PASTE name = Copy the kept buffer under the specified 'name'."
help<-1> = "PASTE f name = Copy the kept buffer as record 'name' in file 'f'."
help<-1> = 'PE + Page Edit mode.'
help<-1> = "PL# + PRINT the current line and the next '#' lines,"
help<-1> = ' do not change the current line pointer.'
help<-1> = "PP# + PAGE.PRINT a window of '#' lines around the current line,"
help<-1> = ' do not change the current line pointer.'
help<-1> = 'PR + Show the PRESTORE commands.'
help<-1> = 'PR# + Run the #th PRESTORE command.'
help<-1> = 'PR#/any + Change the #th PRESTORE command.'
help<-1> = ' where / - is any delimiter character which will also be'
help<-1> = ' used as the command separator.'
help<-1> = 'QUIT (Q) + QUIT - EXIT the program.'
help<-1> = 'QUITK (QK) + QuitKill - EXIT the program, abandon any active SELECT list.'
help<-1> = 'R - Replace the line with prompted for text.'
help<-1> = "R any - REPLACE this line with 'any'."
help<-1> = "R#/any - REPLACE # lines with 'any'."
help<-1> = 'R/// - CHANGE one or more lines (same as C/// command).'
help<-1> = "RA = Show last 20 'CHANGE' commands."
help<-1> = "RA# = Repeat #th 'CHANGE' command."
help<-1> = 'RELEASE + RELEASE the update record LOCK for this file.'
help<-1> = "S - Show last 20 'LOCATE' commands."
help<-1> = "S# - Repeat #th 'LOCATE' command."
help<-1> = 'SAVE - SAVE a copy of this record under the original name.'
help<-1> = "SAVE name - SAVE a copy of this record under the specified 'name'."
help<-1> = "SAVE f name - SAVE a copy of this record as record 'name' in file 'f'."
help<-1> = 'SEQ#//// - Build a sequence. Format is:'
help<-1> = ' SEQ#/from/base/inc/cols'
help<-1> = ' where / - is any delimiter character.'
help<-1> = ' # - number of lines to CHANGE (default 1).'
help<-1> = ' from - is the character string to be replaced.'
help<-1> = ' base - is the start number (defaults to 1).'
help<-1> = ' inc - is the increment (defaults to 1).'
help<-1> = ' cols - restricts the change to a column range.'
help<-1> = "SHOW ON/OFF + toggle overriding 'S'how flag for 'C' command."
help<-1> = " OFF won't show more than a page of changes."
help<-1> = ' If neither ON nor OFF is used, then toggle SHOW flag.'
help<-1> = "SORT seq - Sort the predefined block (seq defaults to 'AL')."
help<-1> = "SORTU seq # Sort unique predefined block ('AL' default seq)."
help<-1> = 'SPACE ON/OFF + Switch SPACE flag for L, LA, LN, LNA commands.'
help<-1> = ' If neither ON nor OFF is used, then toggle SPACE flag.'
help<-1> = ' OFF means that the commands will ignore spaces and tabs.'
help<-1> = 'SPOOL + SPOOL entire record to PRINTER.'
help<-1> = "SPOOL# + SPOOL '#' lines to the PRINTER."
help<-1> = 'SPOOLHELP + SPOOL the HELP listing to the default PRINTER.'
help<-1> = "SPOUT# # SPOO outline (labels, gotos, gosubs) for '#' lines (default all)."
help<-1> = 'SPOUT# CEPS Show Calls, Executes, Performs, and caSe also (* for all).'
help<-1> = "STAMP - INSERT a 'last modified' stamp into the record, which"
help<-1> = " begins with a '*' (for BASIC 'comment'), and contains the"
help<-1> = ' account name, LOGIN name (if different from account name),'
help<-1> = ' date and time. Used to mark when record was last changed.'
help<-1> = 'SV - Synonym for SAVE.'
help<-1> = 'T + Set current line to the TOP (before first line).'
help<-1> = "TC# - Change '#' lines to text or mixed case (default 1)."
help<-1> = 'TC# any Comments and quoted strings are unchanged.'
help<-1> = "TRIM# - TRIM '#' lines (default 1)."
help<-1> = "TRIM# a b = TRIM '#' lines of character 'a' with argument 'b'."
help<-1> = "TRIMB# - TRIMB '#' lines (default 1)."
help<-1> = "TRIMF# - TRIMF '#' lines (default 1)."
help<-1> = "TRIPLE#/any = Copy '#' lines (default 1) into three clones, joined by 'any'."
help<-1> = "TWIN#/any = Copy '#' lines (default 1) into two clones, joined by 'any'."
help<-1> = "UC# - Change '#' lines to upper case (default 1)."
help<-1> = 'UC# any Comments and quoted strings are unchanged.'
help<-1> = 'UNLOAD - Synonym for SAVE.'
help<-1> = 'V + Version information.'
help<-1> = 'WHERE (W) + Show the item and file being ':view:'ed.'
help<-1> = 'WM + Show or change the word marker.'
help<-1> = 'X + QuitKill - EXIT the program, abandon any active SELECT list.'
help<-1> = 'XEQ - The XEQ command allows a user to execute any legal PERFORM'
help<-1> = ' command from within the program. Upon completion of the'
help<-1> = ' command, control will be returned back to the program.'
help<-1> = "XTD any + Convert hexadecimal string 'any' to decimal and display it."
help<-1> = '/any + Same as L99999999/any - NOTE you are left at the bottom.'
help<-1> = ".A# any + APPEND 'any' to command '#' (default 1)."
help<-1> = ".C#/// + CHANGE stack command '#' (default 1). Syntax is like 'C'."
help<-1> = ".D# + DELETE stack command '#' (default 1)."
help<-1> = ".I# any + INSERT 'any' at stack position '#' (default 1)."
help<-1> = ".L# + LIST on the Terminal the last '#' stack commands."
help<-1> = ".R# + RECALL (copy) command '#' to stack position 1."
help<-1> = ".S# n m + SAVE stack n to m as prestore '#' (all default to 1)."
help<-1> = ".U# # UPCASE stack command '#' (default 1)."
help<-1> = ".UL# # lower case stack command '#' (default 1)."
help<-1> = ".UT# # text case stack command '#' (default 1)."
help<-1> = ".X# + EXECUTE stack command '#' (default 1)."
help<-1> = ' The command will be put in stack position 1.'
help<-1> = "+# + Advance current line pointer by '#' lines (default 1)."
help<-1> = "-# + Back up current line pointer by '#' lines (default 1)."
help<-1> = "\ # Set a line tag with default label like 'T#'."
help<-1> = "\any # Set a line tag labelled 'any'."
help<-1> = '\\ # Clear the line tags.'
help<-1> = "]any # Go to the line tag 'any'."
help<-1> = "[any # Go to the line tag 'any'."
help<-1> = '] # Go to the next line tag.'
help<-1> = '[ # Go to the previous line tag.'
help<-1> = ']] # Display the line tags.'
help<-1> = '[[ # Display the line tags.'
help<-1> = "# + Set the current line pointer to the '#' line."
help<-1> = '<# + Sets the starting block pointer to # (current line default).'
help<-1> = '># + Sets the ending block pointer to # (current line default).'
help<-1> = '<># # + Set both block pointers at the same time.'
help<-1> = '^ + Switch UP ARROW on/off to show non-printing characters as'
help<-1> = ' ^nnn where nnn is the decimal equivalent of ASCII code.'
help<-1> = '? + Show various parameters - easier to use than explain.'
end
rest = trim(upcase(rest))
if rest eq am then
hard = true
rest = ''
end else hard = false
disp = ''
stub = ''
if rest eq '' then flag = true else flag = false
if rest eq 'NEW' then disp = 'New Features':am
good = false
xxno = dcount(help,am)
for xx = 1 to xxno
temp = help<xx>
bite = temp[1,len(rest)]
bit = temp[14,1]
if index('-+=#',bit,1)
then temp = temp[1,13]:'-':temp[15,huge]
else bit = ''
if bit ne '' then
flag = false
if bit eq '#' and rest eq 'NEW' then flag = true
if (bit eq '#' or bit eq '+') and rest eq '' then flag = true
if not(viewflag) then
if bit eq 'eq' and rest eq 'NEW' then flag = true
if bit eq '=' or bit eq '-' and rest eq '' then flag = true
end
end
if not(flag) and rest ne '' and bite eq rest then
if bit eq '#' or bit eq '+' then flag = true
if not(viewflag) then
if bit eq '=' or bit eq '-' then flag = true
end
end
if flag then
disp<-1> = temp
good = true
end
next xx
if not(good) then
disp := am
disp<-1> = 'No explanation of "':rest:'" is available.'
disp<-1> = 'For a list of words that have explanations, type "HELP".'
disp := am
end
if hard then gosub print.disp else gosub show.disp
return
show.disp:
write disp on voc,'&DISP.':whom
if stub eq '' then stub = 'Press return to continue showing explanation, Q to quit'
xxno = dcount(disp,am)
pg = 0
for xx = 1 to xxno
pg += 1
if pg ge system(3) then
loop
rlen = 1
gosub get.rope; answ = rope
crt begn:ceol:
answ = trim(upcase(answ))[1,1]
until index('QT-',answ,1) do
repeat
if answ eq 'Q' then return
if answ eq 'T' then xx = 1
if answ eq '-' then
xx -= 2*(system(3)-1)
if xx lt 1 then xx = 1
end
pg = 1
end
crt disp<xx>
next xx
disp = ''
return
print.disp:
printer on
heading upcase(verb):" help file ":timedate():"'LL'"
xxno = dcount(disp,am)
for xx = 1 to xxno
print disp<xx>
next xx
printer close
return
get.page.comd:
gosub get.keyc
do.page.comd:
locate(keyc,keys;cpos) then cpos = acts<cpos> else cpos = 0
begin case
case cpos eq uarr ;* up key
if here le 1 then crt bell:; return
gosub check.page
here -= 1
if prow le 1 then
ptop = ptop - botl
if ptop lt 1 then ptop = 1
gosub disp.page
end
gosub get.line; temp = line
case cpos eq darr ;* down key
if here ge last then crt bell:; return
gosub check.page
here += 1
if prow ge botl then
ptop = ptop + botl
if ptop ge last then ptop = last - botl + 1
if ptop le 1 then ptop = 1
gosub display.page
end
gosub get.line; temp = line
case cpos eq larr ;* left key
if pchr le 1 then crt bell:; return
pchr -= 1
if pchr lt ppos then
gosub check.page
gosub disp.page
end
case cpos eq rarr ;* right key
pchr += 1
if pchr-ppos ge span then
gosub check.page
gosub disp.page
end
case cpos eq upag ;* page up key
gosub check.page
ptop -= botl
if ptop lt 1 then ptop = 1
here -= botl
if here lt 1 then here = 1
pchr = 1
gosub get.line; temp = line
gosub disp.page
case cpos eq dpag ;* page down key
gosub check.page
ptop = ptop + botl
if ptop ge last then ptop = last - botl + 1
here = here + botl
if here gt last then here = last
pchr = 1
gosub get.line; temp = line
gosub disp.page
case cpos eq lpag ;* start of line key
pchr = 1
if pchr lt ppos then gosub check.page; gosub disp.page
case cpos eq rpag ;* end of line key
pchr = len(temp)+1
if pchr lt ppos then gosub check.page; gosub disp.page
if pchr-ppos ge span then
gosub check.page
gosub disp.page
end
case cpos eq tpag ;* top page key
gosub check.page
here = 1
ptop = 1
pchr = 1
gosub disp.page
gosub get.line; temp = line
case cpos eq bpag ;* bottom page key
gosub check.page
here = last
ptop = last - botl + 1
gosub get.line
pchr = len(line)+1
gosub disp.page
gosub get.line; temp = line
case cpos eq escp ;* escape key
if this ne that then
crt @(0,botl):ceol:revb:'ABANDONING CHANGES':revf
end
this = that
here = savl<1>
gosub set.record
mode = 'LINE'
case cpos eq phlp ;* help key
gosub check.page
gosub page.help
case cpos eq zoom ;* Go to line key
crt bott:
stub = 'Go to line :'
stay = pchr
gosub get.rope; numb = trim(rope)
pchr = stay
crt bott:revb:'Press <F1> for help.':revf:
if not(numb matches '1N0N') then numb = here
if numb gt last then numb = last
if numb eq here then return
gosub check.page
here = numb
ptop = here
pchr = 1
gosub disp.page
gosub get.line; temp = line
case cpos eq skey ;* forward search
crt bott:
stub = 'Search: ':'> '
stay = pchr
pick = lastfind; gosub get.rope; lastfind = rope
pchr = stay
crt bott:revb:'Press <F1> for help.':revf:
if lastfind eq '' then return
* is it in this line or the rest of the item?
test = index(temp[pchr+1,huge],lastfind,1)
save = here
gosub check.page
if test then
test += pchr
end else
dawn = here+1
dusk = last
for here = dawn to dusk until test
gosub get.line
test = index(line,lastfind,1)
if test then save = here
next here
end
if test then
if save lt ptop or save ge (ptop+botl) then ptop = save
here = save
pchr = test
gosub disp.page
end else here = save
gosub get.line; temp = line
case cpos eq rkey ;* reverse search
crt bott:
stub = 'Search: ':'< '
stay = pchr
pick = lastfind; gosub get.rope; lastfind = rope
pchr = stay
crt bott:revb:'Press <F1> for help.':revf:
if lastfind eq '' then return
* is it in this line before the cursor position or the rest of the item above?
test = index(temp[1,pchr-1],lastfind,1)
save = here
gosub check.page
if not(test) then
dawn = 1
dusk = here-1
for here = dusk to dawn step -1 until test
gosub get.line
what = count(line,lastfind)
if what then
test = index(line,lastfind,what)
save = here
end
next here
end
if test then
if save lt ptop or save ge (ptop+botl) then ptop = save
here = save
pchr = test
gosub disp.page
end else here = save
gosub get.line; temp = line
case not(sec.write.flg)
crt bell:
case cpos eq delc ;* delete character key
if temp eq '' then return
if pchr eq 1 then
temp = temp[2,len(temp)]
end else
temp = temp[1,pchr-1]:temp[pchr+1,len(temp)]
end
crap = temp[pchr,span-pcol]
convert badc to gudc in crap
crt @(pcol,prow):ceol:crap:
case cpos eq dell ;* delete line key
del this<here>
gosub set.record
gosub disp.page
gosub get.line; temp = line
case cpos eq delr ;* delete to end of line key
if pchr gt len(temp) then
if here ge last then crt bell:; return
line = fmt(temp,'l#':pchr-1):this<here+1>
del this<here>
this<here> = line
gosub set.record
gosub disp.page
gosub get.line; temp = line
end else
temp = temp[1,pchr-1]
this<here> = temp
memr(cell)<lnum> = temp
line = temp
crt @(pcol,prow):ceol:
end
case cpos eq back ;* backspace key
if pchr eq 1 then crt bell:; return
pchr -= 1
temp = temp[1,pchr-1]:temp[pchr+1,len(temp)]
if pchr lt ppos then
gosub check.page
gosub disp.page
end else
pcol = rem(pchr-1,span)
crt @(pcol,prow):ceol:
crap = temp[pchr,span-pcol]
convert badc to gudc in crap
crt crap:
end
case cpos eq carr ;* carriage return key
if pchr eq 1 then
line = ''
end else
line = temp[1,pchr-1]
temp = temp[pchr,len(temp)]
end
if lnum eq 0 then lnum = 1
memr(cell)<lnum> = line
last += 1
lnum += 1
line = temp
gosub insert.line
gosub reset.record
here += 1
pchr = 1
if prow ge botl then
ptop = ptop + botl
if ptop ge last then ptop = last - botl + 1
if ptop le 1 then ptop = 1
gosub display.page
end else gosub disp.page
gosub get.line; temp = line
case cpos eq togg ;* toggle mode key
if mode<2> eq 'Ins' then
mode<2> = 'Rep'
end else mode<2> = 'Ins'
case cpos eq writ ;* write away data key
gosub check.page
mode = 'LINE'
case seq(keyc) lt 28 or seq(keyc) gt 127 or len(keyc) gt 1
crt bell:
case seq(keyc) eq 30 or seq(keyc) eq 31
crt bell:
case 1
if seq(keyc) eq 28 then keyc = char(252)
if seq(keyc) eq 29 then keyc = char(253)
if pchr and len(temp) lt (pchr-1) then
temp = temp:str(' ',pchr)
temp = temp[1,pchr-1]
end
if mode<2> eq 'Ins'
then offset = pchr
else offset = pchr+1
if pchr eq 1
then temp = keyc:temp[offset,len(temp)]
else temp = temp[1,pchr-1]:keyc:temp[offset,len(temp)]
if mode<2> eq 'Ins' then
crt @(pcol,prow):ceol:
crap = temp[pchr,span-pcol]
end else crap = keyc
convert badc to gudc in crap
crt @(pcol,prow):crap:
pchr += 1
if pchr-ppos ge span then
gosub check.page
gosub disp.page
end
end case
return
check.page:
if '*':temp ne '*':line then
memr(cell)<lnum> = temp
gosub reset.record
end
return
page.help:
gosub clear.page
if pagehelp eq '' then
if sec.write.flg then
pagehelp = ''
pagehelp<-1> = ' Page editing help'
pagehelp<-1> = ''
pagehelp<-1> = ' Cursor movement keys Line movement keys'
pagehelp<-1> = ''
pagehelp<-1> = ' UP = <UP arrow> or ^Z LEFT END = <Home> or ^A'
pagehelp<-1> = ' DOWN = <DOWN arrow> or ^J RIGHT END = <End> or ^E'
pagehelp<-1> = ' LEFT = <LEFT arrow> or ^U GO TO LINE = ^G'
pagehelp<-1> = ' RIGHT = <RIGHT arrow> or ^F (prompts for desired line)'
pagehelp<-1> = ''
pagehelp<-1> = ' Page movement keys Deleting keys'
pagehelp<-1> = ''
pagehelp<-1> = ' PREVIOUS = <Page Up> or ^P DELETE CHAR = <Delete> or ^D'
pagehelp<-1> = ' NEXT = <Page Down> or ^N DELETE LINE = <Ctrl-Home> or ^X'
pagehelp<-1> = ' TOP = <Ctrl-Page Up> or ^T DELETE TO EOL = <Ctrl-End> or ^K or ^R'
pagehelp<-1> = ' BOTTOM = <Ctrl-Page Down> or ^B'
pagehelp<-1> = ' <Ctrl-]> = Value Mark'
pagehelp<-1> = ' <Backspace> is destructive <Ctrl-\> = Sub-value Mark'
pagehelp<-1> = ' <Enter> splits the line'
pagehelp<-1> = ' <Insert> or <Tab> toggles between the insert and overwrite modes'
pagehelp<-1> = ''
pagehelp<-1> = ' <F2> or ^W Returns to line editor mode WITH changes'
pagehelp<-1> = ' <Esc> or ^Q Returns without changes'
end else
pagehelp = ''
pagehelp<-1> = ' Page viewing help'
pagehelp<-1> = ''
pagehelp<-1> = ' Cursor movement keys Line movement keys'
pagehelp<-1> = ''
pagehelp<-1> = ' UP = <UP arrow> or ^Z LEFT END = <Home> or ^A'
pagehelp<-1> = ' DOWN = <DOWN arrow> or ^J RIGHT END = <End> or ^E'
pagehelp<-1> = ' LEFT = <LEFT arrow> or ^U GO TO LINE = ^G'
pagehelp<-1> = ' RIGHT = <RIGHT arrow> or ^F (prompts for desired line)'
pagehelp<-1> = ''
pagehelp<-1> = ' Page movement keys '
pagehelp<-1> = ''
pagehelp<-1> = ' PREVIOUS = <Page Up> or ^P '
pagehelp<-1> = ' NEXT = <Page Down> or ^N '
pagehelp<-1> = ' TOP = <Ctrl-Page Up> or ^T'
pagehelp<-1> = ' BOTTOM = <Ctrl-Page Down> or ^B'
pagehelp<-1> = ''
pagehelp<-1> = ''
pagehelp<-1> = ' <Esc> or ^Q Returns without changes'
end
end
disp = pagehelp ; stub = ''
gosub show.disp
crt bott:
stub = 'Press RETURN to continue'
gosub get.rope
gosub display.page
return
get.line:
line = ''
if here eq 0 then
cell = 1
lnum = 0
return
end
if here gt last then return
cell = int((here-1)/cellsize) + 1
coff = rem(here,cellsize)
if ooff and ocel eq cell and ooff eq coff - 1 then
lnum = ooff ; ooff = coff
end else
tlin = memr(cell)
lnum = 0 ; ocel = cell ; ooff = coff
end
loop
remove bite from tlin setting dlim
line = line:bite
while dlim do
if dlim eq 2 then
lnum += 1
if lnum eq coff then exit
line = ''
end else
line = line:char(256-dlim)
end
repeat
if not(dlim) then lnum += 1
return
delete.lines:
chng = 0
if dawn gt dusk then
crt 'No deletion possible - ':dawn:' > ':dusk:'.'
return
end
gosub savethat
chng = dusk - dawn + 1
begin case
case dawn le 1 and dusk ge last
krj = ''
this = ''
beg = 0
fin = 0
case dusk ge last
temp = index(this,am,dawn-1)
this = this[1,temp-1]
if beg gt dawn then beg = 0
if fin gt dawn then fin = 0
for xx = dcount(krj<1>,vm) to 1 step -1
if krj<2,xx> gt dawn then
del krj<1,xx> ; del krj<2,xx> ; krj<3> -= 1
end
next xx
case dawn eq 1
temp = index(this,am,dusk)
this = this[temp+1,len(this)]
if beg le dusk then beg = 0 else beg = beg - chng
if fin le dusk then fin = 0 else fin = fin - chng
for xx = dcount(krj<1>,vm) to 1 step -1
if krj<2,xx> le dusk then
del krj<1,xx> ; del krj<2,xx> ; krj<3> -= 1
end
next xx
case 1
temp = index(this,am,dawn-1)
temp<2> = index(this,am,dusk)
this = this[1,temp<1>]:this[temp<2>+1,len(this)]
if beg ge dawn and beg le dusk then beg = 0 else
if beg gt dusk then beg -= chng
end
if fin ge dawn and fin le dusk then fin = 0 else
if fin gt dusk then fin -= chng
end
for xx = dcount(krj<1>,vm) to 1 step -1
begin case
case krj<2,xx> gt dusk ; krj<2,xx> -= chng
case krj<2,xx> ge dawn
del krj<1,xx> ; del krj<2,xx> ; krj<3> -= 1
end case
next xx
end case
begin case
case here gt dusk
here = here - dusk + dawn - 1
case here gt dawn
here = dawn
end case
gosub set.record
return
check.line:
if '*':temp ne '*':line then
if not(chng) then gosub savethis
chng += 1
memr(cell)<lnum> = temp
if shew or dnum lt plen then gosub display.line
end
return
insert.line:
if here le beg then beg += 1
if here le fin then fin += 1
yyno = dcount(krj<1>,vm)
for yy = 1 to yyno
if krj<2,yy> gt here then krj<2,yy> += 1
next yy
memr(cell) = insert(memr(cell),lnum,0,0,line)
if lfmt and len(last) gt 3 and len(last) ne llen then gosub get.lfmt
return
display.line:
begin case
case last eq 0
here = 0
gosub get.line
crt begn:'Top of empty record.'
case here eq 0
gosub get.line
crt 'Top.'
case here gt last
crt 'Bottom.'
case 1
gosub get.line
if wild then
xxno = len(line)
temp = ''
for xx = 1 to xxno
bite = line[xx,1]
bite = seq(bite)
if bite ge 127 or bite lt 32 then
$ifdef unidata
bite = '^':fmt(bite,'3/0R')
$else
bite = '^':fmt(bite,'R%3')
$endif
end else bite = char(bite)
temp = temp:bite
next xx
line = temp
end else convert badc to gudc in line
crt begn:ceol:
if lfmt then
blk = ': '
if here eq beg then blk = '< '
if here eq fin then blk = '> '
if here eq beg and here eq fin then blk = '<>'
if lfmt then crt (here lfmt):blk:
end
if bleach then
crt line
end else
if here ge beg and here le fin
then showline = @(-13):@(-5):line:@(-6):@(-14)
* else call SORT.LINE(showline,line,1,len(line),lastfind,caseflag)
else setoff = 1 ; width = len(line) ; gosub getshowline
crt showline
end
dnum += 1
if here eq last then crt 'Bottom at line ':last:'.'
end case
return
clear.page:
for xx = system(3)-1 to 0 step -1
crt @(00,xx):ceol:
next xx
return
display.page:
crt clpg
disp.page:
if pchr lt 1 then pchr = 1
gosub clear.page
gosub get.lfmt
crt bott:revb:'Press <F1> for help.':revf:
crt @(0,0):ceol:revb:
if viewflag
then crt 'Viewing "':item:'" in file "':fnam:'"':
else crt 'Editing "':item:'" in file "':fnam:'"':
crt revf:
if idcnt gt 1 then crt ' <':id:'/':idcnt:'> ':
crt
ppos = int((pchr-1)/span)
ppos = span*ppos+1
save = here:am:lnum:am:cell:am:line
for xx = 1 to botl
here = ptop + xx - 1
gosub get.line
if bleach then
disp = line[ppos,span]
convert badc to gudc in disp
end else
convert badc to gudc in line
disp = line
if here ge beg and here le fin
then showline = @(-13):@(-5):disp[ppos,span]:@(-6):@(-14)
* else call SORT.LINE(showline,disp,ppos,span,lastfind,caseflag)
else setoff = ppos ; width = span ; gosub getshowline
disp = showline
end
crt @(0,xx):disp:
next xx
here = save<1>; lnum = save<2>; cell = save<3>; line = save<4>
return
savethis:
oops = this ; oopc = comi ; oopl = save ; oopf = savl
oopb = beg:am:fin ; oopk = krj
* if level eq 0 then write oops on voc, '&LED.':whom
return
savethat:
oops = this ; oopc = comi ; oopl = here ; oopf = last
oopb = beg:am:fin ; oopk = krj
* if level eq 0 then write oops on voc, '&LED.':whom
return
reset.record:
matbuild this from memr using am
set.record:
gosub parse.record
gosub get.line
if len(last) gt 3 and len(last) ne llen then gosub get.lfmt
return
parse.record:
this = this
ocel = '' ; ooff = ''
last = dcount(this,am)
if last eq 0 then
dim memr(1)
mat memr = ''
cell = 1 ; lnum = 0
return
end
numcells = int((last-1)/cellsize)+1
dim memr(numcells)
mat memr = ''
cell = 1
lnum = 0
for cell = 1 to numcells
memr(cell) = field(this,@am,(cell-1)*cellsize+1,cellsize)
next cell
! line = ''
! loop
! remove bite from this setting mark
! line = line:bite
! begin case
! case mark eq 0
! if line ne '' then
! line = line[1,len(line)]
! end
! memr(cell) = line
! case mark eq 2
! lnum += 1
! if lnum ge cellsize then
! memr(cell) = line
! line = ''
! cell += 1
! lnum = 0
! end else
! line = line:char(256-mark)
! end
! case 1
! line = line:char(256-mark)
! end case
! while mark do
! repeat
cell = 1
lnum = 0
return
locked.record:
stub = 'Record is currently locked by another user. Try again? ':ny:' '
gosub get.rope; answ = rope
answ = upcase(trim(answ))
if answ eq 'PASSWORD' then
lock = false
read this from file, item then goto carry.on
end
if answ[1,1] eq yes[1,1] then goto edit.item
return
exec.that:
temp = temp<1>:' ':fnam:' ':item:temp<2>
if fileinfo(file,3) ne '4' then
crt 'Cannot ':temp:' - must be type 1 or 19'
return
end
execute temp
test = @(0,0)
return
parse.rest:
bite = ''
flag = ''
posn = 1
xxno = len(rest)
for xx = 1 to xxno
bit = rest[xx,1]
if flag eq '' then
if bit eq ' ' then
if bite<posn> ne '' then posn += 1
end else
if index(qt,bit,1) then
flag = bit
if keepquot then bite<posn> = bite<posn>:bit
end else
if bit eq '(' then
flag = ')'
if bite<posn> ne '' then posn += 1
bite<posn> = '('
end else bite<posn> = bite<posn>:bit
end
end
end else
if bit ne flag then
bite<posn> = bite<posn>:bit
end else
if keepquot or bit eq ')' then bite<posn> = bite<posn>:bit
posn += 1
flag = ''
end
end
next xx
return
split.itype:
bite = ''
flag = ''
posn = 1
xxno = len(line)
for xx = 1 to xxno
bit = line[xx,1]
if flag eq '' then
if bit eq ';' then
posn += 1
end else
if index(qt,bit,1) then flag = bit
if bit eq '(' then flag = ')'
bite<posn> = bite<posn>:bit
end
end else
if bit eq flag[1,1] then flag = flag[2,huge]
if bit eq '(' and flag[1,1] eq ')' then flag := ')'
bite<posn> = bite<posn>:bit
end
next xx
return
get.lfmt:
* set up the line format
llen = len(last)
if llen lt 3 then llen = 3
$ifdef unidata
lfmt = llen:'/0R'
$else
lfmt = 'R%':llen
if index(item,'_IType.',1) then lfmt = llen:'@R'
$endif
prmt = '*':str('-',llen-1)
return
leftarr: *
numb = oconv(trim(comi[2,len(comi)]),'MCN')
if numb eq '' then numb = here
if numb gt last then numb = ''
if numb ge 0 then
crt 'Block starts at line ':numb:
beg = numb
if fin and beg gt fin then
crt '; End moved from ':fin:' to ':beg
fin = beg
mov = 1
end else
if fin then mov = fin - beg + 1 else mov = last - beg
crt ' (':mov:' lines)'
end
if numb eq here then gosub display.line
end else crt 'Cannot mark line ':numb
return
rightarr: *
numb = oconv(trim(comi[2,len(comi)]),'MCN')
if numb eq '' then numb = here
if numb gt last then numb = ''
if numb ge 0 then
crt 'Block ends at line ':numb:
fin = numb
if beg gt fin then
crt '; Start moved from ':beg:' to ':fin
beg = fin
mov = 1
end else
if beg then mov = fin - beg + 1 else mov = fin
crt ' (':mov:' lines)'
end
if numb eq here then gosub display.line
end else crt 'Cannot mark line ':numb
return
botharr: *
numb = trim(comi[3,len(comi)])
begin case
case numb matches '1N0N'
numb = numb:am:numb
case numb matches '1N0N"-"1N0N'
numb = field(numb,'-',1):am:field(numb,'-',2)
case numb matches '1N0N" "1N0N'
numb = field(numb,' ',1):am:field(numb,' ',2)
case numb eq ''
numb = here:am:here
case 1
numb = ''
end case
if numb<2> gt last then numb<2> = last
if numb<1> gt last then numb = ''
if numb<2> lt numb<1> then
crt 'Block starts at ':numb<1>:' and ends at ':numb<2>:' => ':
numb = ''
end
if numb ne '' then
beg = numb<1>
fin = numb<2>
if beg eq fin then
crt 'Block starts and ends at line ':beg
end else
crt 'Block starts at ':beg:' and ends at ':fin
end
if here eq beg or here eq fin then
gosub display.line
end
end else crt 'Cannot mark Block'
return
recalc.posn:
begin case
case posn lt rest and posn le oopl
case posn lt rest and posn gt oopl
posn += numb
case posn ge rest and posn lt (rest+numb)
posn += (here+1-rest)
case posn ge (rest+numb) and posn le oopl
posn -= numb
end case
return
find.label:
temp = field(trimf(line),' ',1)
temp = trim(temp,char(13),'B')
chit = temp[1,1]
begin case
case chit eq '*' or chit eq '!' ; temp = ''
case chit matches '1N' or chit eq '.'
temp = field(temp,'*',1)
temp = field(temp,'!',1)
temp = field(temp,':',1)
test = convert('.0123456789','',temp)
if test ne '' then temp = ''
case chit matches '1A' and index(temp,':',1)
temp = field(temp,':',1)
test = oconv(oconv(temp,'MC/A'),'MC/N')
test = convert('._%$','',test)
if test ne '' then temp = ''
case 1
temp = ''
end case
return
get.answ:
loop
*>
rlen = 1
*>
gosub get.rope
answ = upcase(trim(rope)[1,1])
until answ eq yes[1,1] or answ eq no[1,1] do
crt 'Please answer Y or N'
repeat
crt
return
writerr:
$ifdef qm
if status() eq er$trigger then
crt 'Data validation error: ': @trigger.return.code
end else
crt 'Write error ': status():' (o/s error %2) - Data not saved. Original data will be lost if you leave the editor now.'
end
$else
crt 'Write error ': status():' (o/s error %2) - Data not saved. Original data will be lost if you leave the editor now.'
$endif
return
indenter:
marg = fr(1) ;* the margin
dent = fr(2) ;* the indentation
supp = fr(6) ;* flag - suppress '!' output
astx = not(fr(9)) ;* flag - keep '*' comments on page edge
suit = not(fr(10)) ;* flag - indent 'CASE' statements
dead = 'ACDGHIJKMPQSVXYZ'
push = 'LOOP\WHILE\UNTIL\FOR\THEN\ELSE\BEGIN\LOCKED\ON~ERROR'
pull = 'UNTIL\WHILE\REPEAT\NEXT\END'
convert '\' to am in push
convert '\' to am in pull
skip = ';:" (' : "'"
marx = '\"' : "'"
bang = false
xxno = dcount(this,am)
dim part(100)
matparse part from this, am
this = ''
bite = ''
first = true
for xx = 1 to xxno
there = rem(xx,100)
if not(there) then
if first then this = bite else this = this:am:bite
first = false
bite = ''
thisline = part(100)
temp = part(0)
matparse part from temp, am
if not(supp) then bang = true; crt '!':
end else thisline = part(there)
if trim(thisline) eq '' then
if first then bite<there> = '' else bite<there+1> = ''
continue
end
note = false
wcnt = 0; more = 0; less = 0
mark = ''; tags = ''; lastword = ''
zz = 1
thisline = trimf(thisline)
if thisline matches '1N0N"*"0X' then
temp = field(thisline,'*',1)
thisline = temp:' ':thisline[col2(),len(thisline)]
end
thatline = upcase(thisline)
thatline = change(thatline, 'ON ERROR', 'ON~ERROR')
left = field(thatline,' ',1)
if num(left) or left[len(left),1] eq ':' then
if not(index(left,'=',1)) then tags = thisline[1,len(left)]
end
if tags gt '' then
thisline = trimf(thisline[col2()+1,len(thisline)])
thatline = trimf(thatline[col2()+1,len(thatline)])
end
zzno = len(thisline)
loop
while zz lt zzno and not(note) do
loop
thisun = thatline[zz,1]
begin case
case mark eq '' and index(marx,thisun,1)
mark = thisun
case mark ne ''
if thisun eq mark then mark = ''
case wcnt and thisun eq ';'
that = field(trim(thatline[zz+1,zzno]),' ',1)
if that[1,3] eq 'REM' then that = ''
if that[1,1] eq '*' then that = ''
if that[1,1] eq '!' then that = ''
if that eq '' then zz = zzno
case wcnt
case thisun eq '!' or thisun eq '$'
note = true; zz = zzno
case thisun eq '*'
if astx then note = true
zz = zzno
case field(thatline,' ',1) eq 'REM'
note = true; zz = zzno
end case
while (index(skip,thisun,1) or mark) and zz lt zzno do
zz += 1
repeat
left = zz
loop
thisun = thatline[zz,1]
until index(skip,thisun,1) or zz gt zzno do
zz += 1
repeat
word = thatline[left,zz-left]
wcnt += 1
if wcnt ne 1 then
if word eq 'WHILE' or word eq 'UNTIL' then word = ' '
if word eq 'NEXT' or word eq 'REPEAT' then
word = ' '
more -= dent
end
if lastword eq 'LOCKED' then more -= dent
end else
if word eq 'LOCKED' or word eq 'THEN' then
if word eq trim(thatline) then less += dent
end
end
if word eq 'CASE' then
if lastword ne 'BEGIN' and lastword ne 'END' then
more += dent
less += dent
end
if suit and lastword eq 'BEGIN' then more += dent
if suit and lastword eq 'END' then less += dent
end
if not(index(dead,word[1,1],1)) then
locate(word,pull;rubbish) then less += dent
test = word ne 'THEN' & word ne 'ELSE' & word ne 'ON~ERROR'
that = trim(thisline[zz,zzno])
if that[1,1] eq ';' then
that = trim(that[2,zzno])[1,3]
if that[1,3] eq 'REM' then that = ''
if that[1,1] eq '*' then that = ''
if that[1,1] eq '!' then that = ''
end
if test or that eq '' then
locate(word,push;rubbish) then
more += dent
end
end
if word eq 'THEN' or word eq 'LOCKED' then
if that eq '' and lastword eq '' then less -= dent
end
if that ne '' and lastword eq '' then
if word eq 'THEN' or word eq 'ELSE' then
more -= dent
less -= dent
end
if word eq 'LOCKED' and trim(that)[1,1] ne '='
then more -= dent ; less -= dent
end
end
lastword = word
repeat
marg -= less
if tags eq '' then pict = '' else pict = 'L#':(len(tags)+1)
if marg gt len(tags) then pict = 'L#':marg
if thisline eq '!' or thisline eq '$' then note = true
if thatline eq 'REM' then note = true
if astx and thisline eq '*' then note = true
if note then
if tags eq '' then pict = '' else pict = 'L#':(len(tags)+1)
end
thisline = trimb(fmt(tags,pict):thisline)
if first then
bite<there> = thisline
end else bite<there+1> = thisline
marg += more
next xx
if bang then crt
if bite ne '' then
if first then this = bite else this = this:am:bite
end
that = ''
return
get.rope:
* If the terminal doesn't support screen addressing, do simple input
if not(editpage) then
crt begn:stub:
*> input rope:
if rlen then
input rope,rlen:
rlen = 0
end else input rope:
*>
return
end
*
* The following variables are used
*
* BARE - what you are going to reveal (the displayed part)
* CRAM - insert mode on (vs overwrite mode)
* PCOL - display position
* STEM - the prefix part of the display line
* ICON - a picture of what you last displayed
* PANS - the PAN increment
* PPOS - the PAN origin
* WIDE - the PAN width
* PULP - SEQ(COMI) - what you get from a key press
* PURE - untouched, a virgin
* POSN - the stack position
* PCHR - text position
pans = int(span/2)
posn = 0
rope = pick; pick = ''
loop
if heap then
stem = prmt:': '
if posn then stem = '*':fmt(posn, "3'0'R"):stem[5,huge]
end else stem = '*':stub
wide = span - len(stem) - 1
pans = int(wide/2)
ppos = 1
pchr = 1
cram = true
icon = space(span)
crt begn : ceol :
pure = true
!&&&
! if nick and trim(rope) = '' then pchr = len(rope)+1 ; pure = false
!&&&
loop
begin case
*> case pchr lt ppos ; ppos -= pans
case pchr lt ppos
loop while pchr lt ppos ; ppos -= pans ; repeat
case pchr ge (ppos+wide)
loop while pchr ge(ppos+wide) ; ppos += pans ; repeat
*> case pchr ge (ppos+wide) ; ppos += pans
end case
bare = stem : rope[ppos, wide]
pcol = 0
if icon ne bare then
yyno = 0
for yy = 1 to span until yyno
if bare[yy,1] ne icon[yy,1] then yyno = yy
next yy
crt @(yyno-1):bare[yyno,span-yyno]:ceol:@(pcol):
icon = bare[1,span]
end
pcol = len(stem) + pchr - ppos
crt @(pcol) :
gosub get.keyc
locate(keyc,keys;cpos) then cpos = acts<cpos> else cpos = 0
pulp = seq(keyc)
if pulp lt 32 or pulp gt 128 then keyc = ''
if pure then
if cpos eq 0 and keyc ne '' then
rope = ''
pchr = 1
end
crt @(0):
if cram then crt '>': else crt '#':
crt @(pcol):
pure = false
end
begin case
case heap and (cpos = uarr or cpos = upag)
if posn lt dcount(stak, vm) then
posn += 1
rope = stak<1,posn>
end
exit
case heap and (cpos = darr or cpos = dpag)
if posn gt 1 then
posn -= 1
rope = stak<1,posn>
end else
posn = 0
rope = ''
end
exit
case heap and cpos = skey
if rope eq '' then
if look<1> eq '' then continue
comi = look<1,1>
gosub parse.command
rope = 'L':dlim:rest
end else rope = 'L/':rope
if rope eq look<1> then rope = 'L'
return
case heap and cpos = rkey
if rope eq '' then
if look<1> eq '' then continue
comi = look<1,1>
gosub parse.command
rope = 'LA':dlim:rest
end else rope = 'LA/':rope
if rope eq look<1> then rope = 'L'
return
case heap and cpos = writ and pulp ne 23
rope = 'PE'
return
case heap and cpos = phlp
stub = '' ; heap = false ; rest = ''
gosub show.help
rope = 'D'
return
case cpos = larr
if pchr gt 1 then pchr -= 1
case cpos = rarr
if pchr le len(rope) then pchr += 1
case cpos = lpag
pchr = 1
case cpos = rpag
pchr = len(rope) + 1
case cpos = escp
posn = 0
rope = ''
exit
case cpos = delc
rope = rope[1, pchr-1] : rope[pchr+1, huge]
case cpos = delr
rope = rope[1, pchr-1]
case cpos = back
if pchr gt 1 then
pchr -= 1
rope = rope[1, pchr-1] : rope[pchr+1, huge]
end
case cpos = carr
if heap then
crt begn : ceol : ':' : rope:
if posn then
if rope eq stak<1,posn> then del stak<1,posn>
end
end
return
case cpos = togg
cram = not(cram)
crt @(0):
if cram then crt '>': else crt '#':
crt @(pcol):
case pulp eq 23 ;* ctrl-w
dope = downcase(rope)
mope = upcase(rope)
tope = oconv(rope,'MCT')
begin case
case rope eq tope and dope eq tope ; rope = mope
case rope eq tope ; rope = dope
case rope eq mope ; rope = tope
case 1 ; rope = mope
end case
case pulp ge 32 and pulp lt 128
if cram then
rope = rope[1, pchr-1] : keyc : rope[pchr, huge]
end else
if pchr le len(rope)
then rope[pchr, 1] = keyc
else rope := keyc
end
pchr += 1
case 1
crt bell:
end case
if rlen and len(rope) ge rlen then
crt keyc:
rlen = 0
return
end
repeat
repeat
return
get.keyc:
$ifdef qm
if not(index(upcase(system(7)),'EEEPC',1)) then
keyc = keycode()
return
end
$endif
common /keys$krj/ termtype,eseq,keyd,base,full
if not(assigned(termtype)) then termtype = ''
if termtype ne oconv(system(7),'MCU') then gosub setup.keys
keyc = ''
loop
$ifdef unidata
mine = in()
$else
mine = keyin()
$endif
locate(mine,base;post) then gosub get.rest
locate(mine,eseq;cmd)
then keyc = char(keyd<cmd>)
else if len(mine) eq 1 then keyc = mine
while keyc eq '' do repeat
return
get.rest:
loop
$ifdef unidata
a = system(12)
loop
until system(12) ge (a+5) do
repeat
$else
nap 5
$endif
input your,-1
while your do
$ifdef unidata
mine := in()
$else
mine := upcase(keyin())
$endif
locate(mine,full,post;your) then return
repeat
return
setup.keys:
* Define the key numbers - these are based on QM keycode()
*======================================================================
* Arrow keys
equ lark to 203, rark to 204, uark to 205, dark to 206
* Page up and down, home and end
equ upak to 207, dpak to 208, homk to 209, endk to 210
* Insert, delete, backtab, delete line, backspace
equ insk to 211, deck to 212, btbk to 213, delk to 127, bspk to 8
* Control - Page up and down, homk and end
equ cupk to 214, cdpk to 215, chok to 216, cenk to 217
* Function, Control+Function, Alt+Function, Shift+Function
equ f1 to 128, cf1 to 140, af1 to 152, sf1 to 164
equ f2 to 129, cf2 to 141, af2 to 153, sf2 to 165
equ f3 to 130, cf3 to 142, af3 to 154, sf3 to 166
equ f4 to 131, cf4 to 143, af4 to 155, sf4 to 167
equ f5 to 132, cf5 to 144, af5 to 156, sf5 to 168
equ f6 to 133, cf6 to 145, af6 to 157, sf6 to 169
equ f7 to 134, cf7 to 146, af7 to 158, sf7 to 170
equ f8 to 135, cf8 to 147, af8 to 159, sf8 to 171
equ f9 to 136, cf9 to 148, af9 to 160, sf9 to 172
equ f10 to 137, cf10 to 149, af10 to 161, sf10 to 173
equ f11 to 138, cf11 to 150, af11 to 162, sf11 to 174
equ f12 to 139, cf12 to 151, af12 to 163, sf12 to 175
*======================================================================
* Stash the escape sequences and key codes in labelled common
termtype = oconv(system(7),'MCU')
* Set up keys good for many terminals and as defaults
eseq = '' ; keyd = ''
keyd<-1> = lark; eseq<-1> = char(21)
keyd<-1> = rark; eseq<-1> = char(6)
keyd<-1> = uark; eseq<-1> = char(26)
keyd<-1> = dark; eseq<-1> = char(10)
keyd<-1> = homk; eseq<-1> = char(1)
keyd<-1> = endk; eseq<-1> = char(5)
keyd<-1> = deck; eseq<-1> = char(4)
keyd<-1> = upak; eseq<-1> = char(27):'[5~'
keyd<-1> = dpak; eseq<-1> = char(27):'[6~'
* Now do settings that don't interfere between terminals
* VT-type terminals - cater for alternative arrow sequences
keyd<-1> = rark; eseq<-1> = char(27):'[C'
keyd<-1> = rark; eseq<-1> = char(27):'OC'
keyd<-1> = uark; eseq<-1> = char(27):'[A'
keyd<-1> = uark; eseq<-1> = char(27):'OA'
keyd<-1> = dark; eseq<-1> = char(27):'[B'
keyd<-1> = dark; eseq<-1> = char(27):'OB'
keyd<-1> = insk; eseq<-1> = char(27):'[1~'
keyd<-1> = deck; eseq<-1> = char(27):'[4~'
keyd<-1> = btbk; eseq<-1> = char(27):'[Z'
keyd<-1> = f1 ; eseq<-1> = char(27):'OP'
keyd<-1> = f2 ; eseq<-1> = char(27):'OQ'
keyd<-1> = f3 ; eseq<-1> = char(27):'OR'
keyd<-1> = f4 ; eseq<-1> = char(27):'OS'
keyd<-1> = f5 ; eseq<-1> = char(27):'OT'
keyd<-1> = f6 ; eseq<-1> = char(27):'[17~'
keyd<-1> = f7 ; eseq<-1> = char(27):'[18~'
keyd<-1> = f8 ; eseq<-1> = char(27):'[19~'
keyd<-1> = f9 ; eseq<-1> = char(27):'[20~'
keyd<-1> = f10 ; eseq<-1> = char(27):'[21~'
keyd<-1> = f11 ; eseq<-1> = char(27):'[23~'
keyd<-1> = f12 ; eseq<-1> = char(27):'[24~'
* Wyse-type terminals
keyd<-1> = insk; eseq<-1> = char(27):'Q'
keyd<-1> = deck; eseq<-1> = char(27):'W'
keyd<-1> = btbk; eseq<-1> = char(27):'I'
keyd<-1> = f1 ; eseq<-1> = char(1):'@':char(13)
keyd<-1> = f2 ; eseq<-1> = char(1):'A':char(13)
keyd<-1> = f3 ; eseq<-1> = char(1):'B':char(13)
keyd<-1> = f4 ; eseq<-1> = char(1):'C':char(13)
keyd<-1> = f5 ; eseq<-1> = char(1):'D':char(13)
keyd<-1> = f6 ; eseq<-1> = char(1):'E':char(13)
keyd<-1> = f7 ; eseq<-1> = char(1):'F':char(13)
keyd<-1> = f8 ; eseq<-1> = char(1):'G':char(13)
keyd<-1> = f9 ; eseq<-1> = char(1):'H':char(13)
keyd<-1> = f10 ; eseq<-1> = char(1):'I':char(13)
keyd<-1> = f11 ; eseq<-1> = char(1):'J':char(13)
keyd<-1> = f12 ; eseq<-1> = char(1):'K':char(13)
* ADDS-type terminals
keyd<-1> = f1 ; eseq<-1> = char(2):'1':char(13)
keyd<-1> = f2 ; eseq<-1> = char(2):'2':char(13)
keyd<-1> = f3 ; eseq<-1> = char(2):'3':char(13)
keyd<-1> = f4 ; eseq<-1> = char(2):'4':char(13)
keyd<-1> = f5 ; eseq<-1> = char(2):'5':char(13)
keyd<-1> = f6 ; eseq<-1> = char(2):'6':char(13)
keyd<-1> = f7 ; eseq<-1> = char(2):'7':char(13)
keyd<-1> = f8 ; eseq<-1> = char(2):'8':char(13)
keyd<-1> = f9 ; eseq<-1> = char(2):'9':char(13)
keyd<-1> = f10 ; eseq<-1> = char(2):':':char(13)
keyd<-1> = f11 ; eseq<-1> = char(2):';':char(13)
keyd<-1> = f12 ; eseq<-1> = char(2):'<':char(13)
* xterm type - like my ASUS eeePC
keyd<-1> = bspk ; eseq<-1> = char(127)
keyd<-1> = delk ; eseq<-1> = char(27):'[3;2~'
keyd<-1> = f5 ; eseq<-1> = char(27):'[15~'
keyd<-1> = sf1 ; eseq<-1> = char(27):'O2P'
keyd<-1> = sf2 ; eseq<-1> = char(27):'O2Q'
keyd<-1> = sf3 ; eseq<-1> = char(27):'O2R'
keyd<-1> = sf4 ; eseq<-1> = char(27):'O2S'
keyd<-1> = sf5 ; eseq<-1> = char(27):'[15;2~'
keyd<-1> = sf6 ; eseq<-1> = char(27):'[17;2~'
keyd<-1> = sf7 ; eseq<-1> = char(27):'[18;2~'
keyd<-1> = sf8 ; eseq<-1> = char(27):'[19;2~'
keyd<-1> = sf9 ; eseq<-1> = char(27):'[20;2~'
keyd<-1> = sf10 ; eseq<-1> = char(27):'[21;2~'
keyd<-1> = sf11 ; eseq<-1> = char(27):'[23;2~'
keyd<-1> = sf12 ; eseq<-1> = char(27):'[24;2~'
* Now do terminal-specific settings
* VT-type terminals
if termtype[1,2] eq 'VT' or termtype[1,5] eq 'XTERM' then
keyd<-1> = lark; eseq<-1> = char(27):'[D'
keyd<-1> = lark; eseq<-1> = char(27):'OD'
end else
keyd<-1> = insk; eseq<-1> = char(27):'[D'
keyd<-1> = deck; eseq<-1> = char(27):'OD'
end
* Wyse-type terminals
if termtype[1,2] eq 'WY' then
keyd<-1> = lark; eseq<-1> = char(8)
keyd<-1> = rark; eseq<-1> = char(12)
keyd<-1> = uark; eseq<-1> = char(11)
keyd<-1> = btbk; eseq<-1> = char(27):'O' ;* !
end
* for my lttle ASUS eeePC & Linux - What a cool thing it is!
if index(termtype,'EEEPC',1) then
keyd<-1> = chok; eseq<-1> = char(27):'[2H' ;* Shift-Home actually
keyd<-1> = homk; eseq<-1> = char(27):'[H'
keyd<-1> = endk; eseq<-1> = char(27):'[F'
keyd<-1> = insk; eseq<-1> = char(27):'[2~'
keyd<-1> = deck; eseq<-1> = char(27):'[3~'
end else
keyd<-1> = homk; eseq<-1> = char(27):'[2~'
keyd<-1> = endk; eseq<-1> = char(27):'[3~'
end
* Populate the escape sequence test variables
base = ''; full = ''
amax = dcount(eseq,am)
for anum = 1 to amax
temp = eseq<anum>
if len(temp) le 1 then continue
locate(temp[1,1],base;post) else
post = dcount(base,am)+1
end
base<post> = temp[1,1]
full<post,-1> = temp
next anum
return
outline:
* to display logic simplisticly
rest = oconv(rest,'MCU')
if index(rest,'*',1) then rest = 'CEPS'
bot = here + 1
if bot gt last then bot = 1
if numb then msup = here + numb else msup = last
if msup gt last then msup = last
for here = bot to msup
gosub get.line
gosub find.label
line = ' ':upcase(line)
begin case
case chit eq '*' or chit eq '!' ; line = ''
case index(line,' GOTO ',1)
case index(line,' GO ',1)
case index(line,' GOSUB ',1)
case rest eq '' ; line = ''
case index(rest,'C',1) and index(line,' ':'CALL',1)
case index(rest,'E',1) and index(line,' ':'EXECUTE',1)
case index(rest,'P',1) and index(line,' ':'PERFORM',1)
case index(rest,'S',1) and index(line,' ':'CASE',1)
case 1 ; line = ''
end case
if temp ne '' or line ne '' then gosub display.line
next here
return
getshowline:
if unassigned(puncs) then
puncs = ', []()<>=+-/*:#!'
funcs = 'ABS\ABSS\ACOS\ADDS\ALPHA\ANDS\ASCII\ASIN\ASSIGNED\'
funcs := 'ATAN\BITAND\BITNOT\BITOR\BITRESET\BITSET\BITTEST\'
funcs := 'BITXOR\CATS\CHANGE\CHAR\CHARS\CHECKSUM\COL1\COL2\'
funcs := 'CONTINUE\CONVERT\COS\COSH\COUNT\COUNTS\DATE\DCOUNT\'
funcs := 'DELETE\DIV\DIVS\DOWNCASE\DQUOTE\DTX\EBCDIC\EQS\'
funcs := 'EREPLACE\EXCHANGE\EXP\EXTRACT\FADD\FDIV\FFIX\FFLT\'
funcs := 'FIELD\FIELDS\FIELDSTORE\FILEINFO\FIX\FMT\FMTDP\'
funcs := 'FMTS\FMTSDP\FMUL\FOLD\FOLDDP\FSUB\GES\GET\'
funcs := 'GETLOCALE\GETREM\GROUP\GTS\ICHECK\ICONV\ICONVS\'
funcs := 'IFS\ILPROMPT\INDEX\INDEXS\INDICES\INMAT\INSERT\INT\'
funcs := 'ISNULL\ISNULLS\ITYPE\KEYIN\LEFT\LEN\LENDP\LENS\'
funcs := 'LENSDP\LES\LN\LOWER\LTS\MATCHFIELD\MAXIMUM\MINIMUM\'
funcs := 'MOD\MODS\MULS\NEG\NEGS\NES\NOT\NOTS\NUM\NUMS\OCONV\'
funcs := 'OCONVS\ORS\PWR\QUOTE\RAISE\REAL\RECORDLOCKED\REM\'
funcs := 'REMOVE\REPLACE\REUSE\RIGHT\RND\RPC.CALL\RPC.CONNECT\'
funcs := 'RPC.DISCONNECT\SADD\SCMP\SDIV\SEEK\SELECTINFO\SEND\'
funcs := 'SENTENCE\SEQ\SEQS\SETLOCALE\SIN\SINH\SLEEP\SMUL\'
funcs := 'SOUNDEX\SPACE\SPACES\SPLICE\SQRT\SQUOTE\SSUB\STATUS\'
funcs := 'STR\STRS\SUBR\SUBS\SUBSTRINGS\SUM\SUMMATION\SYSTEM\'
funcs := 'TAN\TANH\TERMINFO\TIME\TIMEDATE\TPARM\TRANS\TRIM\'
funcs := 'TRIMB\TRIMBS\TRIMF\TRIMFS\TRIMS\UNASSIGNED\'
funcs := 'UNICHAR\UPCASE\XLATE\XTD'
convert '\' to @am in funcs
keywords = 'ABORT\AUTHORIZATION\AUXMAP\BEGIN\BREAK\BSCAN\'
keywords := 'BYTE\BYTELEN\BYTETYPE\BYTEVAL\CALL\CASE\CHAIN\'
keywords := 'CLEAR\CLEARDATA\CLEARFILE\CLEARPROMPTS\CLEARSELECT\'
keywords := 'CLOSE\CLOSESEQ\COMMIT\COMMON\COMPARE\CONSTANTS\'
keywords := 'CONVERT\CREATE\CRT\DATA\DEBUG\DEFFUN\DEL\DELETE\'
keywords := 'DELETELIST\DELETEU\DIM\DIMENSION\DISPLAY\DO\ECHO\ELSE\'
keywords := 'END\ENTER\EQU\EQUATE\ERRMSG\EXECUTE\EXIT\FILELOCK\'
keywords := 'FILEUNLOCK\FIND\FINDSTR\FLUSH\FOOTING\FOR\FORMLIST\'
keywords := 'FUNCTION\GET\GETLIST\GETX\GO\GOSUB\GOTO\GROUPSTORE\'
keywords := 'HEADING\HUSH\IF\INCLUDE\INPUT\INPUTCLEAR\INPUTDISP\'
keywords := 'INPUTDP\INPUTERR\INPUTIF\INPUTNULL\INPUTTRAP\INS\'
keywords := 'KEYEDIT\KEYEXIT\KEYTRAP\LET\LOCALEINFO\LOCATE\LOCK\'
keywords := 'LOOP\MAT\MATBUILD\MATCH\MATCHES\MATPARSE\MATREAD\MATREADL\'
keywords := 'MATREADU\MATWRITE\MATWRITEU\NAP\NEXT\NOBUF\NULL\'
keywords := 'NUMERIC.DATA\ON\OPEN\OPENCHECK\OPENDEV\OPENPATH\'
keywords := 'OPENSEQ\PAGE\PERFORM\PRECISION\PRINT\PRINTER\'
keywords := 'PRINTERR\PROCREAD\PROCWRITE\PROGRAM\PROMPT\'
keywords := 'RANDOMIZE\READ\READBLK\READL\READLIST\READNEXT\'
keywords := 'READSEQ\READT\READU\READV\READVL\READVU\RECORDLOCK\'
keywords := 'RELEASE\REM\REMOVE\REPEAT\RETURN\REVREMOVE\REWIND\'
keywords := 'ROLLBACK\SEEK\SELECT\SELECTE\SELECTINDEX\SETREM\'
keywords := 'SSELECT\START\STATUS\STOP\STORAGE\SUBROUTINE\'
keywords := 'TABSTOP\THEN\TIMEOUT\TO\TPRINT\TRANSACTION\TTYCTL\'
keywords := 'TTYGET\TTYSET\UNICHARS\UNISEQ\UNISEQS\UNLOCK\UNTIL\'
keywords := 'UPRINT\WEOF\WEOFSEQ\WRITE\WRITEBLK\WRITELIST\'
keywords := 'WRITESEQ\WRITESEQF\WRITET\WRITEU\WRITEV\WRITEVU'
convert '\' to @am in keywords
si.label = 1
si.comment = 2
si.string = 3
si.key = 4
si.operator = 5
si.function = 6
si.directive = 7
si.highlight = 8
si.doc = 9
bi.hiword = 10
* Highlights for HostAccess
bo = @(-58) ; bf = @(-59)
wo = @(-5) ; wf = @(-6)
ro = @(-13) ; rf = @(-12)
uo = @(-15) ; uf = @(-12)
hi.commenton = uo:bo
hi.commentoff = uf:bf
hi.labelon = bo
hi.labeloff = bf
hi.selecton = ro:wo
hi.selectoff = wf:rf
hi.stringon = wo
hi.stringoff = wf
hi.keyon = uo
hi.keyoff = uf
hi.opon = ''
hi.opoff = ''
hi.funcon = bo
hi.funcoff = bf
hi.diron = wo
hi.diroff = wf
hi.docon = ro:bo
hi.docoff = rf:bf
end
l = len(line)
* If the line is too long, don't colourise it
if l gt 2000 then
showline = line[setoff,width]
return
end
myline = line
oldmyline = myline
myline = trimf(myline)
mask = space(l - len(myline))
word = myline[' ',1,1]
if word[' ',1,1] match '1N0N' or word match '1A0X":"' then
mask := str(si.label,len(word)):' '
myline = myline[' ',2,999]
word = myline[' ',1,1]
end
begin case
case word[1,1] eq '*' or word[1,1] eq '!'
if count(myline,'@@') then
mask := str(si.doc, l)
end else
mask := str(si.comment, l)
end
case word[1,1] eq '$' or word[1,1] eq '#'
mask := str(si.directive, l)
case 1
dc = count(myline,';')
if not(dc) then
mask := space(l)
end else
foundcomment = false
for z = 1 to dc until foundcomment
word = trimf(myline[';',z+1,1])
if word[1,1] eq '*' or word[1,1] eq '!' then
foundcomment = z
end
next
if foundcomment then
mask := space(len(myline[';',1, foundcomment])):str(si.comment, l)
end else
mask := space(l)
end
end
end case
lin = convert(puncs,str(@fm,len(puncs)), upcase(oldmyline))
dc3 = dcount(lin,@fm)
for q = 1 to dc3
word = lin[@fm,q,1]
st = col1()+ 1
if st gt 1 then
if mask[st-1,1] eq ' ' and oldmyline[st-1,1] ne ' ' then
mask[st-1,1] = si.operator ; * operators too
end
end
begin case
case word[1,1] eq '"'
ix = index(lin[st+1,huge],'"',1)
if ix then
if mask[st,1] eq ' ' then
q = dcount(lin[1, ix+st],@fm)
mask[st, ix+1] = str(si.string, ix+1)
end
end
case word[1,1] eq "'"
ix = index(lin[st+1,huge],"'",1)
if ix then
if mask[st,1] eq ' ' then
q = dcount(lin[1, ix+st],@fm)
mask[st, ix+1] = str(si.string, ix+1)
end
end
case 1
locate(word,keywords;dpos;'AL') then
if mask[st,1] eq ' ' then
mask[st, len(word)] = str(si.key, len(word))
end
end else
locate(word,funcs;dpos;'AL') then
* Functions are followed by a bracket
brak = ''
fpos = len(lin[@fm,1,q])+1
if fpos then brak = trim(oldmyline[fpos,999])[1,1]
if brak eq '(' and mask[st,1] eq ' ' then
mask[st,len(word)] = str(si.function, len(word))
end
end
end
end case
next
word = lastfind
if word ne '' then
oc = 1
loop
if caseflag
then ix = index(oldmyline,word,oc)
else ix = index(upcase(oldmyline),upcase(word),oc)
while ix do
oc += 1
mask[ix, len(word)] = str(si.highlight, len(word))
repeat
end
myline = oldmyline[setoff,width]
mask = mask[setoff,width]
showline = ''
old = ''
l = len(myline)
for k = 1 to l
c = mask[k,1]
if c ne old then
begin case
case old eq si.label
showline := hi.labeloff
case old eq si.comment
showline := hi.commentoff
case old eq si.key
showline := hi.keyoff
case old eq si.string
showline := hi.stringoff
case old eq si.key
showline := hi.keyoff
case old eq si.operator
showline := hi.opoff
case old eq si.function
showline := hi.funcoff
case old eq si.directive
showline := hi.diroff
case old eq si.highlight
showline := hi.selectoff
end case
begin case
case c eq si.label
showline := hi.labelon
case c eq si.comment
showline := hi.commenton
case c eq si.key
showline := hi.keyon
case c eq si.string
showline := hi.stringon
case c eq si.operator
showline := hi.opon
case c eq si.function
showline := hi.funcon
case c eq si.directive
showline := hi.diron
case c eq si.highlight
showline := hi.selecton
case c eq si.doc
showline := hi.docon
end case
old = mask[k,1]
end
showline := myline[k,1]
next
begin case
case old eq si.label
showline := hi.labeloff
case old eq si.comment
showline := hi.commentoff
case old eq si.key
showline := hi.keyoff
case old eq si.string
showline := hi.stringoff
case old eq si.function
showline := hi.funcoff
case old eq si.operator
showline := hi.opoff
case old eq si.directive
showline := hi.diroff
case old eq si.highlight
showline := hi.selectoff
case old eq si.doc
showline := hi.docoff
end case
return