;
; SYSLIB Module Name:  SINLIN
; Author:  Richard Conn
; SYSLIB Version Number:  2.0
; Module Version Number:  1.0
; Module Entry Points:
;	INLINE
; Module External References:
;	CCOUT		CIN		COUT		CRLF
;

;
;  INLINE -- 
;	INPUT LINE EDITOR
;	INPUT A LINE FROM CON: INTO THE BUFFER POINTED TO BY H&L
;	INPUT PARAMETERS:
;		HL PTS TO BUFFER
;		A = ECHO FLAG (A=0 MEANS NO ECHO)
;	OUTPUT PARAMETERS:
;		NO REGS AFFECTED
;	INPUT LINE EDITING CHARACTERS ARE --
;		<BS> -- DELETE PREVIOUS CHAR AND BACK UP CURSOR (SOFTCOPY)
;		<DEL> -- DELETE PREVIOUS CHAR AND ECHO IT (HARDCOPY)
;		<CR> -- INPUT COMPLETE
;		<LF> -- SKIP DOWN TO NEXT LINE AND INSERT <CR> <LF>
;		CTRL-X -- ERASE CURRENT LINE AND BACK UP CURSOR (SOFTCOPY)
;		CTRL-U -- ERASE CURRENT LINE (HARDCOPY)
;		CTRL-R -- RETYPE CURRENT LINE
;		CTRL-E -- GO TO NEXT LINE
;
	EXT	CCOUT
	EXT	CIN
	EXT	COUT
	EXT	CRLF

PUTRG	MACRO
	PUSH	B	; SAVE BC, DE, HL
	PUSH	D
	PUSH	H
	ENDM
GETRG	MACRO
	POP	H	; RESTORE HL, DE, BC
	POP	D
	POP	B
	ENDM


;
;  MAIN INLINE ENTRY POINT
;
INLINE::
	PUTRG		; SAVE REGISTERS
	PUSH	PSW	; SAVE PSW
	STA	ECHO	; SAVE ECHO FLAG
	SHLD	START	; SAVE START OF STRING

;  INLINE RESTART LOOP
INL0:
	LHLD	START	; GET START OF STRING
	MVI	C,0	; SET CHAR COUNT

;  MAIN LOOP
INL1:
	CALL	CIN	; GET INPUT CHAR
	CPI	NULL	; DO NOT PERMIT <NULL>
	JZ	INL1
	CPI	BS	; BACKSPACE?
	JZ	INBS
	CPI	DEL	; DELETE?
	JZ	INDEL
	CPI	TAB	; TABULATE?
	JZ	INTAB
	CPI	CR	; CARRIAGE RETURN?
	JZ	INCR
	CPI	LF	; LINE FEED?
	JZ	INLF
	CPI	CTRLU	; CTRL-U?
	JZ	RESTRT
	CPI	CTRLX	; CTRL-X?
	JZ	REXSTRT
	CPI	CTRLR	; CTRL-R?
	JZ	RETYPE
	CPI	CTRLE	; CTRL-E?
	JZ	NEWLINE
	MOV	M,A	; STORE CHAR
	INX	H	; PT TO NEXT
	CALL	CTRL	; PRINT CHAR
	INR	C	; INCR CHAR CNT
	JMP	INL1




;
;  ** INLINE MODULES **

;  NEWLINE -- ECHO <CR> <LF> AND CONTINUE
NEWLINE:
	CALL	CRLF
	JMP	INL1

;  TAB -- TABULATE TO NEXT TAB STOP
INTAB:
	MOV	M,A	; STORE <TAB>
	INX	H	; PT TO NEXT CHAR POSITION
	CALL	INTAB0	; TABULATE
	JMP	INL1

;  CTRL-R -- RETYPE CURRENT LINE
RETYPE:
	MVI	M,0	; STORE END OF STRING CHAR
	MVI	C,0	; RESET CHAR CNT
	LHLD	START	; GET START ADDRESS
	CALL	HASH	; PRINT HASH CHAR
RETY1:
	MOV	A,M	; GET CHAR
	ORA	A	; ZERO?
	JZ	INL1	; CONTINUE
	CALL	CTRL	; PRINT IT
	MOV	A,M	; GET CHAR AGAIN
	CPI	TAB	; DON'T COUNT IF <TAB>
	JZ	RETY2
	CPI	BEL	; DON'T COUNT IF <BEL>
	JZ	RETY2
	INR	C	; INCR CHAR CNT
RETY2:
	INX	H	; PT TO NEXT CHAR
	JMP	RETY1

;  CTRL-U -- ERASE LINE AND RESTART
RESTRT:
	CALL	HASH	; PRINT HASH CHAR
	JMP	INL0	; START UP AGAIN

;  CTRL-X -- ERASE (AND BACKSPACE) LINE AND RESTART
REXSTRT:
	MOV	A,C	; CHECK FOR EMPTY LINE
	ORA	A	; 0 CHARS?
	JZ	INL0
	CALL	EXBS	; <BS>
	JMP	REXSTRT

;  LINE FEED -- INSERT <CR> <LF> AND ECHO <CR> <LF>
INLF:
	MVI	M,CR	; STORE <CR>
	INX	H	; PT TO NEXT
	MVI	M,LF	; STORE <LF>
	INX	H	; PT TO NEXT
	MVI	C,0	; RESET CHAR CNT
	LDA	ECHO	; ECHO ON?
	ORA	A	; 0=NO
	CNZ	CRLF	; NEW LINE
	JMP	INL1

;  DELETE -- DELETE PREVIOUS CHAR AND ECHO DELETED CHAR
INDEL:
	CALL	BOL	; BEGINNING OF LINE?
	JZ	INL1	; CONTINUE
	DCX	H	; BACK UP
	MOV	A,M	; GET CHAR
	CALL	CTRL	; PRINT CHAR
	CPI	BEL	; DON'T CHANGE COUNT IF <BEL>
	JZ	INL1
	INR	C	; INCR DISPLAY CHAR COUNT
	JMP	INL1

;  BACKSPACE -- DELETE PREVIOUS CHAR AND BACK UP CURSOR
INBS:
	CALL	EXBS	; EXECUTE <BS>
	JMP	INL1

;  BACKSPACE ROUTINE
EXBS:
	CALL	BOL	; BEGINNING OF LINE?
	RZ		; CONTINUE IF SO
	DCR	C	; DECR COUNT
	DCX	H	; BACK UP
	LDA	ECHO	; ECHO ON?
	ORA	A	; 0=NO
	RZ
	MVI	A,BS	; PRINT <BS>
	CALL	COUT
	MVI	A,' '	; <SP>
	CALL	COUT
	MVI	A,BS	; <BS>
	CALL	COUT
	RET

;  CARRIAGE RETURN -- DONE; STORE ENDING ZERO
INCR:
	MVI	M,0	; STORE ENDING ZERO
	LDA	ECHO	; ECHO ON?
	ORA	A	; 0=NO
	CNZ	CRLF	; NEW LINE
	POP	PSW	; RESTORE PSW
	GETRG		; RESTORE REGS
	RET




;
;  ** SUPPORT ROUTINES **
;  BOL -- RETURNS W/ZERO FLAG SET IF USER AT BEGINNING OF LINE
BOL:
	XCHG		; DE=HL
	LHLD	START	; GET START ADR
	XCHG		; HL RESTORED
	MOV	A,D	; CHECK FOR MATCH
	CMP	H	; MATCH?
	RNZ		; NO MATCH
	MOV	A,E	; CHECK FOR COMPLETE MATCH
	CMP	L
	RNZ		; NO MATCH
	PUSH	PSW	; SAVE FLAGS
	MVI	A,BEL	; BEEP
	CALL	COUT
	POP	PSW
	RET

;  CTRL -- IF CHAR>=<SP>, PRINT IT; OTHERWISE, PRINT AS CTRL-CHAR
CTRL:
	PUSH	B	; SAVE BC
	MOV	B,A	; SAVE CHAR IN B
	LDA	ECHO	; CHECK ECHO FLAG
	ORA	A	; 0=NO ECHO
	MOV	A,B	; RESTORE CHAR
	POP	B	; RESTORE BC
	RZ		; NO OUTPUT IF NO ECHO
	CPI	' '	; <SP>?
	JC	CTRL1
	JMP	COUT	; PRINT IT NORMALLY
CTRL1:
	CPI	TAB	; TRAP <TAB>
	JZ	INTAB0
	JMP	CCOUT	; PRINT WITH CTRL-CHAR PROCESSING

;  HASH -- PRINT HASH MARK FOLLOWED BY <CR> <LF>
HASH:
	MVI	A,'#'	; PRINT HASH CHAR
	CALL	COUT
	JMP	CRLF

;  BUFFERS
START:
	DS	2	; TEMPORARY STORAGE FOR BUFFER START ADDRESS
ECHO:
	DS	1	; ECHO FLAG (0=NO ECHO)

;  INTAB0 -- TABULATE ON SCREEN
INTAB0:
	MOV	A,C	; GET CHAR CNT
	ANI	7	; MASK FOR DIFFERENCE FROM 8
	MOV	B,A	; STORE IN REG B TEMPORARILY
	MVI	A,8	; SUBTRACT FROM 8
	SUB	B
	MOV	B,A	; <SP> COUNT IN B
	ADD	C	; ADD TO CHAR COUNT
	MOV	C,A
	LDA	ECHO	; ECHO ON?
	ORA	A	; 0=NO
	RZ
	MVI	A,' '	; <SP> IN A
INTAB1:
	CALL	COUT	; PRINT <SP>
	DCR	B	; COUNT DOWN
	JNZ	INTAB1
	RET

;
;  ASCII SPECIAL CHARACTER EQUATES
;
NULL	EQU	 0	; NULL
BEL	EQU	 7	; BELL
BS	EQU	 8	; BACKSPACE
TAB	EQU	 9	; TAB
LF	EQU	10	; LINE FEED
CR	EQU	13	; CARRIAGE RETURN
CTRLE	EQU	'E'-40H	; CTRL-E
CTRLR	EQU	'R'-40H	; CTRL-R
CTRLU	EQU	'U'-40H	; CTRL-U
CTRLX	EQU	'X'-40H	; CTRL-X
DEL	EQU	7FH	; DELETE CHAR

	END
