	.title	keypad
	.ident	/15aug/
	.mcall	dir$, qiow$, ttsym$

	ttsym$

ttlun	= 5
tiflg	= 1
esc	= 33

; if they press keypad key when buffer at 79 or 80
; then ESC will not be seen or invalid sequence is seen.
; Hence they can only press 78 non-keypad keys before pressing keypad key.
; - NO ONE could be that silly ?
bufsiz	= 80.

	.psect	user$d,d
tt:	qiow$	IO.RNE,ttlun,tiflg,,iostat,,<buff,bufsiz,0>
buff:	.blkb	bufsiz
iostat:	.blkw	2				; iostat area

escp:	.byte	TC.ESQ,1			; SF.SMC esqseq
escsiz	= . - escp

ttyp:	.byte	TC.TTP,0			; terminal type
ttysiz	= . - ttyp

; table of valid terminal types - do vt2?? exist in software yet ?
termt:	.byte	T.V100, T.V101, T.V102, T.V105, T.V125, T.V131, T.V132
	.byte	0				; terminator
						; N.B. same as T.UNKO
	.even

.macro	key 	ascii,number
	.ascii	/ascii/<number>
.endm

; table to map 3rd chr from keypad sequence to a number.
table:	key	p,0				; 0
	key	q,1				; 1
	key	r,2				; 2
	key	s,3				; 3
	key	t,4				; 4
	key	u,5				; 5
	key	v,6				; 6
	key	w,7				; 7
	key	x,8.				; 8
	key	y,9.				; 9

	key	P,10.				; PF1
	key	Q,11.				; PF2
	key	R,12.				; PF3
	key	S,13.				; PF4

	key	m,14.				; -
	key	l,15.				; ,
	key	M,16.				; Enter
	key	n,17.				; .
	.byte	0				; terminator
	.even

;
; keypad returns a digit indicating which key has been pressed on
; keypad.
; NB has been put into alternate keypad mode previously.
;
	.psect	user$i

keypad::
	tst	(r5)+				; discard nargs
	mov	#tt,r0				; assume unfiddled with
10$:	dir$	r0				; and do it
	cmpb	#IE.EOF,iostat			; ^Z ?
	bne	20$				; br, if no
	mov	#-1,@(r5)+			; return -1
	return

; easy way - seems too difficult to check is.suc, is.esc, is.cr etc...
;
20$:	mov	#buff,r1			; escape in buffer ?
	mov	#bufsiz,r2
30$:	cmpb	(r1)+,#esc			; esc ??
	beq	40$				; br, if yes
	sob	r2,30$
						; else no escape in buffer
	br	10$				; and start again

40$:	cmpb	(r1)+,#'O			; next character must be O
	bne	10$				; and start again

	movb	(r1)+,r2			; 3rd chr => r2
	mov	#table,r1			; check valid 3rd chr

50$:	tstb	@r1				; end of table ?
	beq	10$				; and start again

	cmpb	(r1)+,r2			; valid ??
	beq	60$				; br, if yes
	inc	r1				; skip over number
	br	50$

60$:	movb	@r1,@(r5)+			; and return key no
	return


; zero the buffer after a read, successful or otherwise
clrbuf:	mov	#buff,r3
	mov	#bufsiz,r4
10$:	clrb	(r3)+
	sob	r4,10$
	return


;
; attach terminal for duration of CALC and set ESQSEQ
;
ttatt::	tst	(r5)+				; discard nargs
	mov	#tt,r0				; attach tt
	mov	#IO.GTS,Q.IOFN(r0)		; see what we got ....
	mov	#buff,q.iopl(r0)		; use buff for return
	mov	#8.,q.iopl+2(r0)		; and size 8. bytes
	dir$	r0				; do it....
	bcc	10$				; br, if no error
	cmpb	#IE.IFC,iostat			; IO.GTS not sysgened ??
	bne	60$				; br, if ne, don't know it
	mov	#-1,r1				; -1 = GTS not SYSGENED
	br	70$

; SF.GMC/SMC supported ??
10$:	bit	#f2.sch,buff+2			; SF.SMC supported ?
	beq	20$				; br, if no
	bit	#f2.gch,buff+2			; SF.GMC supported ?
	bne	30$				; br, if yes
20$:	mov	#-2,r1				; -2 = SF.GMC/SMC not SYSGENED
	br	70$

; vt100 like terminal ?
30$:	mov	#SF.GMC,Q.IOFN(r0)
	mov	#ttyp,Q.IOPL(r0)		; address
	mov	#ttysiz,Q.IOPL+2(r0)		; size
	dir$	r0				; do it
	movb	ttyp+1,r1			; put terminal type in register
	mov	#termt,r2			; get pointer to valid terminals

40$:	tstb	@r2				; end of table ??
	bne	50$				; br, if no
	mov	#-3,r1				; -3 = not VT100 type terminal
	br	70$

50$:	cmpb	(r2)+,r1			; is this our terminal ??
	bne	40$				; br, if not this one

	mov	#IO.ATT!TF.ESQ,Q.IOFN(r0)	; PHEW !!, he cried
	dir$	r0				; finally DO IT....
	bcc	80$
60$:	mov	#-4,r1				; -4 = unknown error

70$:	mov	r1,@(r5)+			; set error flag
	mov	#IO.RNE,Q.IOFN(r0)		; function Read No Echo
	mov	#buff,q.iopl(r0)		; buffer address
	mov	#bufsiz,q.iopl+2(r0)		; buffer length
	return

80$:	mov	#SF.GMC,Q.IOFN(r0)		; see if set /escseq set
	mov	#escp,Q.IOPL(r0)		; address
	mov	#escsiz,Q.IOPL+2(r0)		; size
	dir$	r0				; do it....
	bcs	60$				; error
	movb	escp+1,r1			; save what ever it was

	movb	#1,escp+1			; make function SET /ESCSEQ
	mov	#SF.SMC,Q.IOFN(r0)		; set /escseq
	dir$	r0				; do it....
	bcs	60$				; error
	movb	r1,escp+1			; set up their default
	clr	r1				; clear error flag
	br	70$				; restore default

;
; detach terminal CALC and set ESQSEQ
;
ttdet::	tst	(r5)+				; discard nargs
	clr	@(r5)				; clear error flag
	mov	#tt,r0				; attach tt
	mov	#IO.DET,Q.IOFN(r0)
	dir$	r0
	bcc	30$
10$:	mov	#-1,@(r5)+			; set error flag
20$:	mov	#IO.RNE,Q.IOFN(r0)		; function Read No Echo
	mov	#buff,q.iopl(r0)		; buffer address
	mov	#bufsiz,q.iopl+2(r0)		; buffer length
	return

30$:						; escp+1 already set up
						; with user default
	mov	#SF.SMC,Q.IOFN(r0)
	mov	#escp,Q.IOPL(r0)		; address
	mov	#escsiz,Q.IOPL+2(r0)		; size
	dir$	r0				; do it....
	bcs	10$
	br	20$

	.end
