RGUTEDT ;CAIRO/DKM - Screen-oriented line editor;04-Sep-1998 11:26;DKM
;;2.1;RUN TIME LIBRARY;;Mar 22, 1999
;=================================================================
; Inputs:
; RGDATA = Data to edit
; RGLEN = Maximum length of data
; RGX = Starting column position
; RGY = Starting row position
; RGVALD = List of valid inputs (optional)
; RGDISV = DISV node to save under (optional)
; RGTERM = Valid input terminators (default=<CR>)
; RGABRT = Valid input abort characters (default=none)
; RGRM = Right margin setting (default=IOM or 80)
; RGQUIT = Exit code (returned)
; RGOPT = Input options
; C = Mark <CR> with ~
; E = Echo off
; H = Horizontal scroll
; I = No timeout
; L = Lowercase only
; O = Overwrite mode
; Q = Quiet mode
; R = Reverse video
; T = Auto-terminate
; U = Uppercase only
; V = Up/down cursor keys terminate input
; X = Suppress auto-erase
; Outputs:
; Return value = Edited data
;=================================================================
ENTRY(RGDATA,RGLEN,RGX,RGY,RGVALD,RGOPT,RGDISV,RGTERM,RGABRT,RGRM,RGQUIT) ;
N RGZ,RGZ1,RGZ2,RGSAVE,RGINS,RGAE,RGBUF,RGTAB,RGPOS,RGEON,RGLEFT,RGBEL,RGMAX,RGRVON,RGRVOFF,RGC,RGW
S RGVALD=$G(RGVALD),RGOPT=$$UP^XLFSTR($G(RGOPT)),RGBEL=$S(RGOPT'["Q":$C(7),1:""),RGDISV=$G(RGDISV)
S:$G(RGTERM)="" RGTERM=$C(13) ; Valid line terminators
S RGABRT=$G(RGABRT) ; Valid input abort keys
S RGRVON=$C(27,91,55,109),RGRVOFF=$C(27,91,109) ; Reverse video control
S RGINS=RGOPT'["O" ; Default mode = insert
S RGAE=RGOPT'["X" ; Auto-erase option
S RGEON=RGOPT'["E" ; No echo option
I RGOPT["I"!'$D(DTIME) N DTIME S DTIME=9999999999 ; Suppress timeout option
S RGBUF=""
S RGRM=$G(RGRM,$G(IOM,80)) ; Display width
S RGTAB=$C(9) ; Tab character
S RGX=$G(RGX,$X),RGY=$G(RGY,$Y),RGW=RGRM-RGX
S:RGW'>0 RGW=1
S:'$G(RGLEN) RGLEN=RGW ; Default field width
S RGMAX=$S(RGOPT["H":250,1:RGLEN) ; Maximum data length
S (RGSAVE,RGDATA)=$E($G(RGDATA),1,RGMAX) ; Truncate data if too long
I $$NEWERR^%ZTER N $ET S $ET=""
S @$$TRAP^RGZOSF("ERROR^RGUTEDT")
D RM^RGZOSF(0)
X ^%ZOSF("EOFF")
F Q:RGDATA'[RGTAB S RGZ=$P(RGDATA,RGTAB),RGDATA=RGZ_$J("",8-($L(RGZ)#8))_$P(RGDATA,RGTAB,2,999)
RESTART D RESET
AGAIN F RGQUIT=0:0 Q:RGQUIT D NXT S RGAE=0
X ^%ZOSF("EON")
W $$XY^RGUT(RGX,RGY),$S(RGOPT["R":RGRVOFF,1:"")
I RGDISV'="" Q:"^^"[RGDATA RGDATA S:RGDATA=" " RGDATA=$G(^DISV(DUZ,RGDISV))
S:RGDISV'="" ^DISV(DUZ,RGDISV)=RGDATA
Q RGDATA ; Return to calling routine
NXT D POSCUR() ; Position cursor
R *RGC:DTIME ; Next character typed
I RGC=27 D ESC Q:'RGC
I RGC<1!(RGABRT[$C(RGC)) S RGDATA=U,RGQUIT=1 Q
I RGTERM[$C(RGC) D TERM Q
I RGC<28 D:RGC'=27 @("CTL"_$C(RGC+64)) Q
I RGC=127!(RGC=240) D CTLH Q
I RGC>64,RGC<91,RGOPT["L" S RGC=RGC+32
E I RGC>96,RGC<123,RGOPT["U" S RGC=RGC-32
I $L(RGVALD),RGVALD'[$C(RGC) D RAISE^RGZOSF()
D:RGAE CTLK,POSCUR() ; Erase buffer if auto erase on
D INSW($C(RGC))
S RGQUIT=RGPOS=RGLEN&(RGOPT["T")
Q
CTLA S RGINS='RGINS ; Toggle insert mode
Q
CTLB D MOVETO(0) ; Move cursor to beginning
Q
CTLX S RGDATA=RGSAVE ; Restore buffer to original
G RESET
CTLE D MOVETO($L(RGDATA)) ; Move cursor to end
Q
CTLI D INSW($J("",8-(RGPOS#8))) ; Insert expanded tab
Q
CTLJ F RGZ=RGPOS:-1:1 Q:$A(RGDATA,RGZ)'=32 ; Find previous nonspace
F RGZ=RGZ:-1:1 Q:$A(RGDATA,RGZ)=32 ; Find previous space
S RGBUF=$E(RGDATA,RGZ,RGPOS) ; Save deleted portion
S RGDATA=$E(RGDATA,1,RGZ-1)_$E(RGDATA,RGPOS+1,RGLEN) ; Remove word
D MOVETO(RGZ-1)
Q
CTLK S RGBUF=RGDATA ; Save buffer
S RGDATA="" ; Erase buffer
D RESET
Q
CTLL S RGBUF=$E(RGDATA,RGPOS+1,RGLEN) ; Save deleted portion
S RGDATA=$E(RGDATA,1,RGPOS) ; Truncate at current position
D DSPLY(RGPOS)
Q
CTLM D POSCUR(RGPOS),INSW("~"):RGOPT["C",MOVETO(RGPOS-$X+RGX+RGW)
Q
CTLR D INSW(RGBUF) ; Insert at current position
Q
CTLT D CTLL
Q
CTLU S RGBUF=$E(RGDATA,1,RGPOS) ; Save deleted portion
S RGDATA=$E(RGDATA,RGPOS+1,RGLEN) ; Remove to left of cursor
D RESET
Q
CTLH I 'RGPOS W RGBEL Q
D LEFT
CTLD S RGDATA=$E(RGDATA,1,RGPOS)_$E(RGDATA,RGPOS+2,RGMAX) ; Delete character to left
D DSPLY(RGPOS,1)
Q
TERM S RGQUIT=2
Q
ESC R *RGZ:1
R:RGZ>0 *RGZ:1
S RGC=0
G UP:RGZ=65,DOWN:RGZ=66,RIGHT:RGZ=67,LEFT:RGZ=68 ;Execute code
S RGC=27
Q
DSPLY(RGP1,RGP2) ;
Q:'RGEON ; Refresh buffer display starting at position RGP1
N RGZ,RGZ1
S RGP1=+$G(RGP1,RGLEFT),RGZ=$E(RGDATA,RGP1+1,RGLEFT+RGLEN),RGP2=$S($D(RGP2):RGP2+$L(RGZ),1:RGLEN-RGP1+RGLEFT)
S:RGP2>RGLEN RGP2=RGLEN
S RGZ=RGZ_$J("",RGP2-$L(RGZ))
F D Q:RGZ=""
.D POSCUR(RGP1)
.S RGZ1=RGRM-$X
.S:RGZ1<1 RGZ1=1
.W $E(RGZ,1,RGZ1)
.S RGZ=$E(RGZ,RGZ1+1,999),RGP1=RGP1+RGZ1
Q
INSW(RGTXT) ;
S:RGPOS>$L(RGDATA) RGDATA=RGDATA_$J("",RGPOS-$L(RGDATA)) ; Pad if past end of buffer
S RGDATA=$E($E(RGDATA,1,RGPOS)_RGTXT_$E(RGDATA,RGPOS+2-RGINS,RGMAX),1,RGMAX)
D DSPLY(RGPOS,0),MOVETO(RGPOS+$L(RGTXT))
Q
POSCUR(RGP) ;
N RGZX,RGZY
S RGP=+$G(RGP,RGPOS),RGZX=RGP-RGLEFT,RGZY=RGZX\RGW+RGY,RGZX=RGZX#RGW+RGX
W $$XY^RGUT(RGZX,RGZY)
Q
MOVETO(RGP) ;
I RGP>RGMAX!(RGP<0) W RGBEL Q
S RGPOS=RGP,RGP=RGLEFT
S:RGPOS<RGLEFT RGLEFT=RGPOS-RGW-1
S:RGLEFT+RGLEN<RGPOS RGLEFT=RGPOS-RGW+1
S:RGLEFT'<RGMAX RGLEFT=RGMAX-RGW
S:RGLEFT<0 RGLEFT=0
D DSPLY():RGLEFT'=RGP,POSCUR()
Q
UP I RGOPT["V" S RGQUIT=3
E D MOVETO(RGPOS-RGW)
Q
DOWN I RGOPT["V" S RGQUIT=4
E D MOVETO(RGPOS+RGW)
Q
RIGHT D MOVETO(RGPOS+1)
Q
LEFT D MOVETO(RGPOS-1)
Q
RESET W $S(RGOPT["R":RGRVON,1:RGRVOFF)
S (RGPOS,RGLEFT)=0 ; Current edit offset
D DSPLY() ; Refresh display
Q
ERROR W RGBEL ; Sound bell
S @$$TRAP^RGZOSF("ERROR^RGUTEDT")
G AGAIN
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HRGUTEDT 7563 printed Dec 13, 2024@02:37:13 Page 2
RGUTEDT ;CAIRO/DKM - Screen-oriented line editor;04-Sep-1998 11:26;DKM
+1 ;;2.1;RUN TIME LIBRARY;;Mar 22, 1999
+2 ;=================================================================
+3 ; Inputs:
+4 ; RGDATA = Data to edit
+5 ; RGLEN = Maximum length of data
+6 ; RGX = Starting column position
+7 ; RGY = Starting row position
+8 ; RGVALD = List of valid inputs (optional)
+9 ; RGDISV = DISV node to save under (optional)
+10 ; RGTERM = Valid input terminators (default=<CR>)
+11 ; RGABRT = Valid input abort characters (default=none)
+12 ; RGRM = Right margin setting (default=IOM or 80)
+13 ; RGQUIT = Exit code (returned)
+14 ; RGOPT = Input options
+15 ; C = Mark <CR> with ~
+16 ; E = Echo off
+17 ; H = Horizontal scroll
+18 ; I = No timeout
+19 ; L = Lowercase only
+20 ; O = Overwrite mode
+21 ; Q = Quiet mode
+22 ; R = Reverse video
+23 ; T = Auto-terminate
+24 ; U = Uppercase only
+25 ; V = Up/down cursor keys terminate input
+26 ; X = Suppress auto-erase
+27 ; Outputs:
+28 ; Return value = Edited data
+29 ;=================================================================
ENTRY(RGDATA,RGLEN,RGX,RGY,RGVALD,RGOPT,RGDISV,RGTERM,RGABRT,RGRM,RGQUIT) ;
+1 NEW RGZ,RGZ1,RGZ2,RGSAVE,RGINS,RGAE,RGBUF,RGTAB,RGPOS,RGEON,RGLEFT,RGBEL,RGMAX,RGRVON,RGRVOFF,RGC,RGW
+2 SET RGVALD=$GET(RGVALD)
SET RGOPT=$$UP^XLFSTR($GET(RGOPT))
SET RGBEL=$SELECT(RGOPT'["Q":$CHAR(7),1:"")
SET RGDISV=$GET(RGDISV)
+3 ; Valid line terminators
if $GET(RGTERM)=""
SET RGTERM=$CHAR(13)
+4 ; Valid input abort keys
SET RGABRT=$GET(RGABRT)
+5 ; Reverse video control
SET RGRVON=$CHAR(27,91,55,109)
SET RGRVOFF=$CHAR(27,91,109)
+6 ; Default mode = insert
SET RGINS=RGOPT'["O"
+7 ; Auto-erase option
SET RGAE=RGOPT'["X"
+8 ; No echo option
SET RGEON=RGOPT'["E"
+9 ; Suppress timeout option
IF RGOPT["I"!'$DATA(DTIME)
NEW DTIME
SET DTIME=9999999999
+10 SET RGBUF=""
+11 ; Display width
SET RGRM=$GET(RGRM,$GET(IOM,80))
+12 ; Tab character
SET RGTAB=$CHAR(9)
+13 SET RGX=$GET(RGX,$X)
SET RGY=$GET(RGY,$Y)
SET RGW=RGRM-RGX
+14 if RGW'>0
SET RGW=1
+15 ; Default field width
if '$GET(RGLEN)
SET RGLEN=RGW
+16 ; Maximum data length
SET RGMAX=$SELECT(RGOPT["H":250,1:RGLEN)
+17 ; Truncate data if too long
SET (RGSAVE,RGDATA)=$EXTRACT($GET(RGDATA),1,RGMAX)
+18 IF $$NEWERR^%ZTER
NEW $ETRAP
SET $ETRAP=""
+19 SET @$$TRAP^RGZOSF("ERROR^RGUTEDT")
+20 DO RM^RGZOSF(0)
+21 XECUTE ^%ZOSF("EOFF")
+22 FOR
if RGDATA'[RGTAB
QUIT
SET RGZ=$PIECE(RGDATA,RGTAB)
SET RGDATA=RGZ_$JUSTIFY("",8-($LENGTH(RGZ)#8))_$PIECE(RGDATA,RGTAB,2,999)
RESTART DO RESET
AGAIN FOR RGQUIT=0:0
if RGQUIT
QUIT
DO NXT
SET RGAE=0
+1 XECUTE ^%ZOSF("EON")
+2 WRITE $$XY^RGUT(RGX,RGY),$SELECT(RGOPT["R":RGRVOFF,1:"")
+3 IF RGDISV'=""
if "^^"[RGDATA
QUIT RGDATA
if RGDATA=" "
SET RGDATA=$GET(^DISV(DUZ,RGDISV))
+4 if RGDISV'=""
SET ^DISV(DUZ,RGDISV)=RGDATA
+5 ; Return to calling routine
QUIT RGDATA
NXT ; Position cursor
DO POSCUR()
+1 ; Next character typed
READ *RGC:DTIME
+2 IF RGC=27
DO ESC
if 'RGC
QUIT
+3 IF RGC<1!(RGABRT[$CHAR(RGC))
SET RGDATA=U
SET RGQUIT=1
QUIT
+4 IF RGTERM[$CHAR(RGC)
DO TERM
QUIT
+5 IF RGC<28
if RGC'=27
DO @("CTL"_$CHAR(RGC+64))
QUIT
+6 IF RGC=127!(RGC=240)
DO CTLH
QUIT
+7 IF RGC>64
IF RGC<91
IF RGOPT["L"
SET RGC=RGC+32
+8 IF '$TEST
IF RGC>96
IF RGC<123
IF RGOPT["U"
SET RGC=RGC-32
+9 IF $LENGTH(RGVALD)
IF RGVALD'[$CHAR(RGC)
DO RAISE^RGZOSF()
+10 ; Erase buffer if auto erase on
if RGAE
DO CTLK
DO POSCUR()
+11 DO INSW($CHAR(RGC))
+12 SET RGQUIT=RGPOS=RGLEN&(RGOPT["T")
+13 QUIT
CTLA ; Toggle insert mode
SET RGINS='RGINS
+1 QUIT
CTLB ; Move cursor to beginning
DO MOVETO(0)
+1 QUIT
CTLX ; Restore buffer to original
SET RGDATA=RGSAVE
+1 GOTO RESET
CTLE ; Move cursor to end
DO MOVETO($LENGTH(RGDATA))
+1 QUIT
CTLI ; Insert expanded tab
DO INSW($JUSTIFY("",8-(RGPOS#8)))
+1 QUIT
CTLJ ; Find previous nonspace
FOR RGZ=RGPOS:-1:1
if $ASCII(RGDATA,RGZ)'=32
QUIT
+1 ; Find previous space
FOR RGZ=RGZ:-1:1
if $ASCII(RGDATA,RGZ)=32
QUIT
+2 ; Save deleted portion
SET RGBUF=$EXTRACT(RGDATA,RGZ,RGPOS)
+3 ; Remove word
SET RGDATA=$EXTRACT(RGDATA,1,RGZ-1)_$EXTRACT(RGDATA,RGPOS+1,RGLEN)
+4 DO MOVETO(RGZ-1)
+5 QUIT
CTLK ; Save buffer
SET RGBUF=RGDATA
+1 ; Erase buffer
SET RGDATA=""
+2 DO RESET
+3 QUIT
CTLL ; Save deleted portion
SET RGBUF=$EXTRACT(RGDATA,RGPOS+1,RGLEN)
+1 ; Truncate at current position
SET RGDATA=$EXTRACT(RGDATA,1,RGPOS)
+2 DO DSPLY(RGPOS)
+3 QUIT
CTLM DO POSCUR(RGPOS)
if RGOPT["C"
DO INSW("~")
DO MOVETO(RGPOS-$X+RGX+RGW)
+1 QUIT
CTLR ; Insert at current position
DO INSW(RGBUF)
+1 QUIT
CTLT DO CTLL
+1 QUIT
CTLU ; Save deleted portion
SET RGBUF=$EXTRACT(RGDATA,1,RGPOS)
+1 ; Remove to left of cursor
SET RGDATA=$EXTRACT(RGDATA,RGPOS+1,RGLEN)
+2 DO RESET
+3 QUIT
CTLH IF 'RGPOS
WRITE RGBEL
QUIT
+1 DO LEFT
CTLD ; Delete character to left
SET RGDATA=$EXTRACT(RGDATA,1,RGPOS)_$EXTRACT(RGDATA,RGPOS+2,RGMAX)
+1 DO DSPLY(RGPOS,1)
+2 QUIT
TERM SET RGQUIT=2
+1 QUIT
ESC READ *RGZ:1
+1 if RGZ>0
READ *RGZ:1
+2 SET RGC=0
+3 ;Execute code
if RGZ=65
GOTO UP
if RGZ=66
GOTO DOWN
if RGZ=67
GOTO RIGHT
if RGZ=68
GOTO LEFT
+4 SET RGC=27
+5 QUIT
DSPLY(RGP1,RGP2) ;
+1 ; Refresh buffer display starting at position RGP1
if 'RGEON
QUIT
+2 NEW RGZ,RGZ1
+3 SET RGP1=+$GET(RGP1,RGLEFT)
SET RGZ=$EXTRACT(RGDATA,RGP1+1,RGLEFT+RGLEN)
SET RGP2=$SELECT($DATA(RGP2):RGP2+$LENGTH(RGZ),1:RGLEN-RGP1+RGLEFT)
+4 if RGP2>RGLEN
SET RGP2=RGLEN
+5 SET RGZ=RGZ_$JUSTIFY("",RGP2-$LENGTH(RGZ))
+6 FOR
Begin DoDot:1
+7 DO POSCUR(RGP1)
+8 SET RGZ1=RGRM-$X
+9 if RGZ1<1
SET RGZ1=1
+10 WRITE $EXTRACT(RGZ,1,RGZ1)
+11 SET RGZ=$EXTRACT(RGZ,RGZ1+1,999)
SET RGP1=RGP1+RGZ1
End DoDot:1
if RGZ=""
QUIT
+12 QUIT
INSW(RGTXT) ;
+1 ; Pad if past end of buffer
if RGPOS>$LENGTH(RGDATA)
SET RGDATA=RGDATA_$JUSTIFY("",RGPOS-$LENGTH(RGDATA))
+2 SET RGDATA=$EXTRACT($EXTRACT(RGDATA,1,RGPOS)_RGTXT_$EXTRACT(RGDATA,RGPOS+2-RGINS,RGMAX),1,RGMAX)
+3 DO DSPLY(RGPOS,0)
DO MOVETO(RGPOS+$LENGTH(RGTXT))
+4 QUIT
POSCUR(RGP) ;
+1 NEW RGZX,RGZY
+2 SET RGP=+$GET(RGP,RGPOS)
SET RGZX=RGP-RGLEFT
SET RGZY=RGZX\RGW+RGY
SET RGZX=RGZX#RGW+RGX
+3 WRITE $$XY^RGUT(RGZX,RGZY)
+4 QUIT
MOVETO(RGP) ;
+1 IF RGP>RGMAX!(RGP<0)
WRITE RGBEL
QUIT
+2 SET RGPOS=RGP
SET RGP=RGLEFT
+3 if RGPOS<RGLEFT
SET RGLEFT=RGPOS-RGW-1
+4 if RGLEFT+RGLEN<RGPOS
SET RGLEFT=RGPOS-RGW+1
+5 if RGLEFT'<RGMAX
SET RGLEFT=RGMAX-RGW
+6 if RGLEFT<0
SET RGLEFT=0
+7 if RGLEFT'=RGP
DO DSPLY()
DO POSCUR()
+8 QUIT
UP IF RGOPT["V"
SET RGQUIT=3
+1 IF '$TEST
DO MOVETO(RGPOS-RGW)
+2 QUIT
DOWN IF RGOPT["V"
SET RGQUIT=4
+1 IF '$TEST
DO MOVETO(RGPOS+RGW)
+2 QUIT
RIGHT DO MOVETO(RGPOS+1)
+1 QUIT
LEFT DO MOVETO(RGPOS-1)
+1 QUIT
RESET WRITE $SELECT(RGOPT["R":RGRVON,1:RGRVOFF)
+1 ; Current edit offset
SET (RGPOS,RGLEFT)=0
+2 ; Refresh display
DO DSPLY()
+3 QUIT
ERROR ; Sound bell
WRITE RGBEL
+1 SET @$$TRAP^RGZOSF("ERROR^RGUTEDT")
+2 GOTO AGAIN