	page	78,132
	title	Serial I/O driver for Monitor

LineLen	=	132

	.model	small
	.code
	.data

	public	LineBuf

LineBuf		db	LineLen dup(0)
ColumnPos	db	0

DGroup	group	_TEXT,_DATA

	.code

	public	InBuf, OutCh, InCh, CrLf

	extrn	Backup:near, Command:near

;Get input line
	assume	cs:DGroup,ds:DGroup

INBUF:
	MOV	DI,offset DGroup:LINEBUF	;Next empty buffer location
	XOR	CX,CX		;Character count
GETCH:
	CALL	InCh		;Get input character
	CMP	AL,20H		;Check for control characters
	JC	CONTROL
	CMP	AL,7FH		;RUBOUT is a backspace
	JZ	BACKSP
	CALL	OutCh		;Echo character
	STOSB			;Put in input buffer
	INC	CX		;Bump character count
	CMP	CX,LineLen	;Buffer full?
	JBE	GETCH		;Drop in to backspace if full
BACKSP:
	JCXZ	GETCH		;Can't backspace over nothing
	DEC	DI		;Drop pointer
	DEC	CX		;and character count
	CALL	BACKUP		;Send physical backspace
	jmp	GETCH		;Get next char.

CONTROL:
	CMP	AL,3		;Ctrl-C?
	JZ	KILL
	cmp	al,1BH		;ESC?
	jz	Kill
	CMP	AL,8		;Check for backspace
	JZ	BACKSP
	CMP	AL,13		;Check for carriage return
	JNZ	GETCH		;Ignore all other control char.
	STOSB			;Put the car. ret. in buffer
;Convert unquoted input to upper case
	MOV	SI,offset DGroup:LINEBUF
	mov	di,si
CaseChk:
	lodsb
	cmp	al,"a"
	jb	NoConv
	cmp	al,"z"
	ja	NoConv
	sub	al,"a"-"A"		;Convert to upper case
NoConv:
	stosb				;Put it back where we got it
	cmp	al,13			;End of line?
	jz	InDone
	cmp	al,'"'
	jz	QuotScan
	cmp	al,"'"
	jnz	CaseChk
QuotScan:
	mov	ah,al			;Remember which quote mark
KillStr:
	lodsb
	stosb
	cmp	al,13
	jz	InDone
	cmp	al,ah
	jnz	KillStr
	jmp	CaseChk

InDone:
	mov	si,offset DGroup:LINEBUF ;Set up SI for command processing

;Output CR/LF sequence

CRLF:
	MOV	AL,13
	CALL	OutCh
	MOV	AL,10
	jmp	short OutCh

;Cancel input line

KILL:
	CALL	CRLF
CommandJ:
	JMP	COMMAND

;Character input routine

InCh:
	push	dx
	xor	dx,dx			;Select COM1
	MOV	AH,2			;Read character
	INT	14H			;Call ROM BIOS for a character
	pop	dx
	RET


;Console output of character in AL
	assume	ds:nothing,es:nothing,ss:nothing

OutCh:
	push	ax			;Character to output on stack
	push	dx
	xor	dx,dx			;Select COM1
	and	al,7FH
	cmp	al," "
	jb	ControlChar
	inc	[ColumnPos]
NoIncCol:
	mov	ah,1			;Write char to COM1
	int	14H
TabDone:
	pop	dx
	pop	ax
	ret

ControlChar:
	cmp	al,9			;Tab character?
	jz	SerTab
	cmp	al,13
	jz	SerCr
	cmp	al,8			;Backspace?
	jnz	NoIncCol
;Backspace
	dec	[ColumnPos]
	jmp	NoIncCol

SerCr:
	mov	[ColumnPos],0
	jmp	NoIncCol

SerTab:
	push	cx
	mov	al,[ColumnPos]
	and	ax,7			;Look at low 3 bits of column
	mov	cx,8
	sub	cx,ax			;cx = no. of char to move
	add	[ColumnPos],cl
TabLoop:
	mov	ax,1*100H + " "		;Write a blank
	int	14H
	loop	TabLoop
	pop	cx
	jmp	TabDone

	end
