.; SCRED.CMD is a single-screen editor. The active function
.; keys are:
.;	The arrows - move cursor in the given direction;
.;	PF1 - coarse motion - multiplies vertical arrows by 8,
.;		and horizontal arrows by 16.

.; Required ICP initialization:

	.ENABLE SUBSTITUTION
	.DISABLE DISPLAY
	.DISABLE DETACH
	.ENABLE ESCAPE-SEQUENCE

.; Required TT: driver initialization (must come after the
.;		.ENABLE ESCAPE-SEQUENCE):

	.SETN TIWID <TICWID>
	.SETS MCR ""
	.IF <CLI> <> "MCR"	.SETS MCR "MCR "
	'MCR'SET /LOWER=TI:
	'MCR'SET /ESCSEQ=TI:
	'MCR'SET /BUF=TI:132.

.; Useful symbol definitions:

	.; The following are suitable for ASCII terminals:

	.SETN NJUNK 16			! Define SO to be a
	.SETS SO "'NJUNK%V'"		!    <Shift Out> char.
	.SETN NJUNK 17			! Define SI to be a
	.SETS SI "'NJUNK%V'"		!    <Shift In> char.
	.SETN NJUNK 33			! Define ESCAPE to be
	.SETS ESCAPE "'NJUNK%V'"	!    an <ESC> character
	.SETN NJUNK 217			! Define SS3 to be an
	.SETS SS3 "'NJUNK%V'"		!    <SS3> (="<ESC>O")
	.SETN NJUNK 233			! Define CSI to be a
	.SETS CSI "'NJUNK%V'"		!    <CSI> (="<ESC>[")

	.; The following are suitable for ANSI terminals:

	.SETS HOME ESCAPE+"[H"		! HOME homes cursor
	.SETS CLEAR ESCAPE+"[J"		! CLEAR clears screen

	.; The following initializes a DEC VT100 or VT200
	.; series terminal by homing and clearing the screen,
	.; loading the normal ASCII character set into G0 and
	.; the graphics character set into G1, and selecting G0.

	.SETS INIT HOME+CLEAR+ESCAPE+"(B"+ESCAPE+")0"+SI

	.GOTO ENTRY			! Skip subroutines.


.; And, some useful subroutines:

	.;
	.;	.GOSUB ASKE line;column
	.;
	.; Positions the cursor at the given line and column,
	.; and issues a .ASKS. On return,
	.;	TEXT contains the text part of the answer;
	.;	ESCSEQ contains the escape sequence;
	.;	<STRLEN> contains the location of the escape
	.;	    character.
	.;
.ASKE:
	.GOSUB POSITN 'COMMAN%C'
	.SETS ESCSEQ ""
	.ASKS TEXT 'COMMAN'
	.IFT <EOF>	.RETURN
	.TEST TEXT ESCAPE
	.IF <STRLEN> = 0	.TEST TEXT CSI
	.IF <STRLEN> = 0	.TEST TEXT SS3
	.IF <STRLEN> <> 0	.SETS ESCSEQ TEXT[<STRLEN>:*]
	.IF <STRLEN> <> 0	.SETS TEXT TEXT[1:<STRLEN>-1]
	.TEST TEXT
	.RETURN

	.;
	.;	.GOSUB POSITN line;column
	.;
	.; returns the escape sequence in COMMAN.
	.;
	.; The following is suitable for an ANSI terminal.
	.;
.POSITN:
	.SETS COMMAN ESCAPE+"["+"'COMMAN%C'"+"H"
	.RETURN



.ENTRY:	.;
	.; This is basicly just a "screen painter". It lets you
	.; motor around the screen with the cursor keys, dropping
	.; characters in as you see fit. All the "tools" given
	.; above are assumed to be around somewhere.
	.;

	.; The following code is unrelated to screen handling.
	.; It initializes the editor, picks up the name of the
	.; input file, and loads it if possible.

	.ENABLE CONTROL-Z
	.ENABLE OVERFLOW
	.SETS SPACES "                                        "
	.SETS SPACES SPACES+SPACES
	.SETN LINE 0.
.INITLP:
	.INC LINE
	.SETS LINE'LINE' SPACES
	.IF LINE < 23.	.GOTO INITLP

	.SETS FILE P1
	.IF FILE = ""	.SETS FILE "SCREEN.DAT"

	;'INIT'
	.TESTFILE 'FILE'
	.IF <FILERR> <> 1	.GOTO EDITOR
	.OPENR 'FILE'
	.SETN LINE 0.
.INPLP:
	.INC LINE
	.READ LINE'LINE'
	.IFT <EOF>	.GOTO INPCLO
	.TEST LINE'LINE'
	.IF <STRLEN> > 80.	.SETS LINE'LINE' LINE'LINE'[1:80.]
	.IF <STRLEN> < 80.	.SETS LINE'LINE' LINE'LINE'+SPACES[<STRLEN>:79.]
	.GOSUB POSITN 'LINE';1
	.SETS COMMAN COMMAN+LINE'LINE'+HOME
	;'COMMAN'
	.IF LINE < 23.	.GOTO INPLP

.INPCLO:.CLOSE

	.; Initialize the editor-specific part of the screen 
	.; handler. This screen handler is specific to an ANSI 
	.; terminal.

.EDITOR:.;

	.; Define parameters used in processing the arrow keys:
	.; These are defined by:
	.;	.SETS ARROWx "axis,fac,sign,limit,test"
	.;   where:
	.;	x	= last character of escape sequence;
	.;	axis	= name of symbol to update;
	.;	fac	= factor to apply if PF1 in effect;
	.;	sign	= direction of travel along axis;
	.;	limit	= limiting value on the axis;
	.;	test	= type of test to make against limit.

	.SETS ARROWA "LINE,8,-,1.,<"	 ! <CSI>A = Up arrow.
	.SETS ARROWB "LINE,8,+,23.,>"	 ! <CSI>B = Down arrow.
	.SETS ARROWC "COLUMN,16,+,80.,>" ! <CSI>C = Right arrow.
	.SETS ARROWD "COLUMN,16,-,1.,<"	 ! <CSI>D = Left arrow.

	.; Define the initial cursor position:

	.SETN LINE 1.
	.SETN COLUMN 1.

	.; Initialise the parse by turning off the "GOLD" key:

.LOOPI:
	.SETF GOLD


.; Main input loop:

	.; Ask for data, and insert the text part into the line
	.; buffers:

.LOOP:
	.GOSUB ASKE 'LINE';'COLUMN'
	.IFT <EOF>	.GOTO CLENUP
	.SETS JUNK LINE'LINE'[1:COLUMN-1]
	.SETN COLUMN COLUMN+<STRLEN>
	.IF COLUMN > 80.	.SETN COLUMN 80.
	.SETS LINE'LINE' JUNK+TEXT+LINE'LINE'[COLUMN:*]
	.SETS LINE'LINE' LINE'LINE'[1:80.]


.; Initialize the escape sequence parser:

.ESCPSI:
	.SETS ESCTYP "INI"	! Set parser "state".
	.SETN ESCAMX 0.		! Set number of arguments.
	.SETN ESCA0 0.		! Clear the first argument.

.; Main parser loop:

	.; Strip off the next character (if any), convert it to 
	.; a number, and do a "computed" GO TO based on current 
	.; parser state and character code:

.ESCPSR:
	.IF ESCSEQ = ""	.GOTO LOOP	! If done, get more.
	.SETS CHAR ESCSEQ[1:1]		! Get first character,
	.SETS ESCSEQ ESCSEQ[2:*]	!  remove from buffer.
	.SETN CVALUE 'CHAR%V'		! Get its value.
	.ONERR LOOPI			! Trap unexpected chars.
	.GOTO 'ESCTYP''CVALUE'		! Handle this character.

	.; First character = <ESC>; set state:

.INI33:	.SETS ESCTYP "ESC"		! Go to escape "state".
	.GOTO ESCPSR			! Get next character.

	.; First character is <SS3>, or

.INI217:.;

	.; First was <ESC> and second is "O"; set state:

.ESC117:.SETS ESCTYP "SS3"		! Go to SS3 "state".
	.GOTO ESCPSR			! Get next character.

	.; Got <SS3>P = PF1 - use it as shift key:

.SS3120:.SETT GOLD			! Set shift flag.
	.GOTO ESCPSI			! Get next escape seq.

	.; First character is <CSI>, or

.INI233:.;

	.; First was <ESC> and second is "["; set state:

.ESC133:.SETS ESCTYP "CSI"		! Go to CSI "state".
	.GOTO ESCPSR			! Get next character.

	.; In a <CSI> sequence, and have a decimal digit:

.CSI60:	.;
.CSI61:	.;
.CSI62:	.;
.CSI63:	.;
.CSI64:	.;
.CSI65:	.;
.CSI66:	.;
.CSI67:	.;
.CSI70:	.;
.CSI71:	.;
	.;				! Accumulate parameter.
	.SETN ESCA'ESCAMX' ESCA'ESCAMX'*10.+CVALUE-60
	.GOTO ESCPSR			! Get next character.

	.; In a <CSI> sequence, and got a ";"; End of parameter:

.CSI73:	.SETN ESCAMX ESCAMX+1.		! Have another param.
	.SETN ESCA'ESCAMX' 0.		! Initialize it.
	.GOTO ESCPSR			! Get next character.

	.; An arrow key generates these escape sequences:

.CSI101:.;	<CSI>A = Up arrow;
.CSI102:.;	<CSI>B = Down arrow;
.CSI103:.;	<CSI>C = Right arrow;
.CSI104:.;	<CSI>D = Left arrow.

	.PARSE ARROW'CHAR' "," AXIS FAC SIGN LIMIT TEST
	.IF ESCA0 = 0	.SETN ESCA0 1.	! Force param.
	.IFT GOLD .SETN ESCA0 ESCA0*'FAC'.	! Apply PF1.
	.SETN NJUNK 'AXIS'		! Save old location.
	.SETN 'AXIS' 'AXIS''SIGN'ESCA0	! Set new loc.
	.IF 'AXIS' 'TEST' 'LIMIT'	.SETN 'AXIS' 'LIMIT'
	.SETF GOLD			! Clear shift key.
	.GOTO ESCPSR			! Get next character.

	.; The following code is (mostly) unrelated to screen 
	.; handling. It is entered on input of a control/Z. The 
	.; output file is written, and the buffer size of the 
	.; terminal is restored.

.CLENUP:.OPEN 'FILE'
	.SETN LINE 0.
.OUTLP:
	.INC LINE
	.SETS JUNK LINE'LINE'
	.DATA 'JUNK'
	.IF LINE < 23.	.GOTO OUTLP
	.CLOSE
	;'INIT'
	.ENABLE DISPLAY
	'MCR'SET /BUF=TI:'TIWID%D'.
	.EXIT
