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