	.title	ttio - a keyboard capture package
;++
;
;	Rev 1.1
;
;	Functions:
;
;	TTINIT	- initialize terminal for ttio
;	TTRDY	- return 1 if key has been pressed
;	TTREAD	- read 1 character from keyboard buffer. If empty, wait.
;	TTFLSH	- flush keyboard buffer
;	MONITR	- terminate task and restore characteristics
;	TTREST	- restore terminal characteristics
;	TTWRT	- write buffer to terminal
;
;--
	.mcall	qiow$s,qio$s,stop$s,setf$s,clef$s,wtse$s,astx$s
	.mcall	ttsym$, alun$s

.macro	savreg
	jsr	r5,$savr1
.endm	savreg

	.psect	c$data,d,rw

bufsiz	==	127.		; Buffer size
kbsiz::	.word	0		; Characters entered
kbbuf::	.blkb	bufsiz		; Keyboard buffer

	.even

buf1::	.word	0

	ttsym$

smctbl::
;	.byte	tc.bin,1	; Read-pass-all
	.byte	tc.pth,1	; Passthru
	.byte	tc.nec,1	; No echo
	.byte	tc.smr,1	; Lower
	.byte	tc.8bc,1	; EBC
	.byte	tc.acr,0	; Nowrap
	.byte	tc.fdx,1	; Full duplex
	.byte	tc.hld,0	; No hold
	.byte	tc.tsy,1	; Process XON/XOFF
	.byte	tc.cts,0	; Cancel ^S...

tab1siz	== . - smctbl

exitbl:
;	.byte	tc.bin,0
	.byte	tc.pth,0
	.byte	tc.nec,0
	.byte	tc.smr,0
	.byte	tc.8bc,0
	.byte	tc.acr,0
	.byte	tc.fdx,0	; Full duplex
	.byte	tc.hld,0	; No hold
	.byte	tc.tsy,0	; Process XON/XOFF
ani:	.byte	tc.ani,0
scp:	.byte	tc.scp,0

tab2siz	== . - exitbl


	.even

extxt::	.ascii	<15><12>/>/
exsiz	== . - extxt
	.even

	.psect	c$code,i,ro

;
;	Initialize
;

ttinit::savreg			; Save registers
ini2:	qiow$s	#sf.gmc,#5,,,,,<#exitbl,#tab2siz> ; Get old characteristics
	qiow$s	#sf.smc,#5,,,,,<#smctbl,#tab1siz> ; Set terminal to binary
	qiow$s	#io.ata,#5,#1,,,,<#fixast>
	br	tfl2		; ...and flush

;
;	Flush buffer
;

ttflsh::savreg			; Save registers
tfl2:	clr	kbsiz		; Flush string
	clef$s	#5.		; Mark empty
	return

;
;	Restore buffer and terminate (STOP) task.
;

monitr::savreg			; Save registers
	call	ttres2		; Restore terminal
	qiow$s	#io.wvb,#5,#2,,,,<#extxt,#exsiz,#0> ; Write prompt
	stop$s			; Stop task
	jmp	ini2		; Initiate terminal

;
;	Restore terminal characteristics
;

ttrest::savreg					; Save registers
ttres2:	qio$s	#sf.smc,#5,,,,,<#exitbl,#tab2siz> ; Restore terminal
	qiow$s	#io.det,#5,#2,,,,<>
	return

;
;	Read character, EF 8 used for flagging
;

ttread::savreg			; Save registers
	tstb	kbsiz		; Any character entered?
	bne	retch		; Yes, return it
	wtse$s	#5.		; No, wait until it becomes
retch:	mov	#kbbuf,r1	; Get pointer to buffer.
	mov	r1,r2		; Copy pointer.
	clr	r0		; Get character.
	bisb	(r2)+,r0
	dec	kbsiz		; Get length of buffer.
	beq	2$		; Done...
	mov	kbsiz,r3
1$:	movb	(r2)+,(r1)+	; Copy down buffer.
	sob	r3,1$
2$:	clef$s	#5		; Clear flag.
	return

;
;	Return 0 if buffer empty, otherwise 1
;

ttrdy::	savreg			; Save registers
	clr	r0		; Clear flag
	tst	kbsiz		; Anything there yet?
	beq	1$		; Nope
	inc	r0		; Yes, change into a 1
1$:	return

;
;	Put character to terminal
;
;	ttwrt(buffer,length)
;		char *buffer;
;		int length;
;
ttwrt::	mov	2(sp), r2	; Buffer location
	mov	4(sp), r3	; Buffer size

	qiow$s	#io.wvb,#5,#2,,,,<r2,r3,#0>	; Go write it
;	qio$s	#io.wvb,#5,,,,,<r2,r3,#0>	; Go write it

	return			; Restore registers and exit

;
;	Two checks...
;
isansi::
	clr	r0
	tstb	ani+1
	beq	10$
	inc	r0
10$:	return
;
isscope::
	clr	r0
	tstb	scp+1
	beq	10$
	inc	r0
10$:	return

;
;	AST service entry
;

fixast:	mov	r0,-(sp)	; Save register
	mov	kbsiz,r0	; Size
	movb	2(sp),kbbuf(r0)	; Copy character
	inc	kbsiz		; Bump length.
	mov	(sp)+,r0
	tst	(sp)+		; Pop off character
	setf$s	#5.		; Flag for character entered
	astx$s			; ...and return control

;
;	Routine for saving registers
;

$savr1:	mov	r4,-(sp)
	mov	r3,-(sp)
	mov	r2,-(sp)
	mov	r1,-(sp)
	mov	#1$,-(sp)
	jmp	(r5)
1$:	mov	(sp)+,r1
	mov	(sp)+,r2
	mov	(sp)+,r3
	mov	(sp)+,r4
	mov	(sp)+,r5
	rts	pc

	.end

