;       SCCSID = @(#)kbdread.asm	6.1 91/02/15
;	SCCSID = @(#)kbdread.asm	6.3 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;
;	Modification History
;
;	14-Aug-86 (billme) Change status flag to use cs segment.
;
;	23-Sep-86 (davidsi) Changed the keyboard status check from the int16
;		  to the int21 call.  Added an int21 keyboard wait loop to
;		  process any special chars (CtrlC, Ctrl-PrtSc).
;
;	15-Jan-87 (billme): Replace initial pushes and final pops
;	with calls to __api_begin and __api_end resp.  This will
;	reduce the size of FAPI and allow support for signals.
;
;	11-June-87 (CWY): after call to kbd_prep, need to check for errors.
;
;
	Page	60,132
;/*************** START OF SPECIFICATIONS ******************************/
;/*								       */
;/* SUBROUTINE NAME: KbdCharIn					       */
;/*								       */
;/* DESCRIPTIVE NAME: Keyboard Character Input			       */
;/*								       */
;/* FUNCTION:  Read a character and scan code from the standard input  */
;/*	       device.						       */
;/*								       */
;/* NOTES:  Status can only be 0 or 40H.  No interim character support.*/
;/*	    KbdHandle is ignored for Version 1.0.		       */
;/*								       */
;/* ENTRY POINT:						       */
;/*	    LINKAGE:  EXTRN KbdCharIn:FAR			       */
;/*								       */
;/* INPUT:	      push@ other CharData			       */
;/*		      push  WORD  IOWait			       */
;/*		      push  WORD  KbdHandle			       */
;/*		      call  kbdCharIn				       */
;/*								       */
;/* EXIT-NORMAL:  AX = 0					       */
;/*								       */
;/* EXIT-ERROR:	 AX = Error Code				       */
;/*								       */
;/* EFFECTS:							       */
;/*								       */
;/* INTERNAL REFERENCES:					       */
;/*    ROUTINES:						       */
;/*								       */
;/* EXTERNAL REFERENCES:					       */
;/*    ROUTINES:						       */
;/*								       */
;/*************** END OF SPECIFICATIONS ********************************/

	.xlist
	include kbdfapi.inc
	include dos2equ.inc
	include error2.inc

	EXTRN	api_get_extended:far	 ;@@ support for DOSErrorClass
	EXTRN	__api_begin:near
	EXTRN	__api_end:near
	EXTRN	kbd_prep:near
	EXTRN	kbd_rest:near
	EXTRN	SignalCheck:near					;THG
	EXTRN	StatusFlag:BYTE
	EXTRN	KbdType:BYTE		; cpd12 (1082)
	.list

CHARIN	STRUC			; stack frame snap shot

		dw	?	; BP
		dw	?	; IP
		dw	?	; CS
		dw	?	; dummy keyboard handle (0)
	IO_Wait dw	?	; iowait
	Char_D	dd	?	; CharData address

CHARIN	ENDS


DSEG	SEGMENT BYTE	PUBLIC	'DATA'

DSEG	ENDS


	PUBLIC	KBDCHARIN

_TEXT	segment byte public 'CODE'
	assume	CS:_TEXT,DS:NOTHING

KBDCHARIN	PROC	FAR
;THG
;THG	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
;THG				; required to save: bp,bx,cx,dx,ds,es
	xor	ax,ax			; AX <- 0 (default locals size) ;THG
	push	bp							;THG
	mov	bp,sp							;THG
	sub	sp,ax			; setup local stack frame	;THG
	push	ds			; save all registers except AX	;THG
	push	es							;THG
	push	bx							;THG
	push	cx							;THG
	push	dx							;THG
	push	si							;THG
	push	di							;THG


		call	kbd_prep		; @@ Ensure handle 0 is CON
		jnc	over			; cpd12 (p1082)
		jmp	error_exit
over:
		mov	cx,[bp].IO_Wait		; get IOWait parameter
		cmp	cx,1			; above 1 ?
		jbe	Start			; no, OK!
		mov	ax,ERROR_KBD_INVALID_IOWAIT
		jmp	short KbdCharexit	; error exit
Start:
		lds	bx,[bp].Char_D		; set up address to CharData

		;;DPL;; I added the following stuff to keep from calling...
		;;DPL;; ...GetKbdStat (which interprets Ctl-C,S,P) in RAW mode.

		Test CS:[StatusFlag],RAW_NOECHO ;Check if raw mode.
		JZ  KbdCooked			;Hop ahead if not.
		Cmp CX,WAITIO			;Check if "wait" okay.
		JE  KbdGetChar			;If so Int16 will block if req.
		Mov AH,1			;Else, check first if...
		add ah,cs:[KbdType]		; cpd12 (1082)
		Int 16h				;...keystroke available.
		JZ  CantWait			;If not, quit now.
		Jmp Short KbdGetChar		;Else, go ahead and call BIOS.

		;;DPL;; End of my added code. This comment and the one just
		;;DPL;; up above may be removed at any time.

KbdCooked:
		mov	ah,D2_GetKbdStat
		int	21H
		or	al,al

		jnz	kbdGetChar		; YES, go get it
		cmp	cx,WAITIO		; NO, wait for character?
		je	KbdWait			; yes
CantWait:
		xor	ax,ax
		mov	[bx].Status,al		; no, return immediate
		jmp	short KbdCharExit

KbdWait:
		mov	ah,D2_GetKbdStat
		int	21H
		or	al,al
		jz	KbdWait
KbdGetChar:					; avail-wait / not avail-wait
		mov	ah,0			; console input without echo
		add	ah,cs:[KbdType]		; cpd12 (1082)
		int	16H			; BIOS keyboard I/O
		mov	[bx].Char,al		; return character
		mov	[bx].Scan,ah		; return scan code
		mov	ax,BIOS_SEGMENT
		mov	es,ax			; get current shift state
		mov	ax,es:[KBDFLAG]		;   from BIOS
		mov	[bx].Shifts,ax		; return BIOS shift state
		mov	ah,2CH			; get time
		int	21H			; pc/dos call
		mov	[bx].hours,ch		; return time
		mov	[bx].minutes,cl
		mov	[bx].seconds,dh
		mov	[bx].tenths,dl
		mov	[bx].Status,CHAR_AVAIL	; return status
		mov	[bx].NLS_Shift,NULL	; NLS shift state
		xor	ax,ax			; no errors returned
KbdCharExit:
		mov	dx,ax			;@@ (dx) = error code
		call	kbd_rest		;@@ Restore previous handle 0
		jc	kcix			;@@
		mov	ax,dx			;@@ (ax) = error code
		jmp	short kcix		;@@
error_exit:	call	api_get_extended	;@@
kcix:
	call	SignalCheck						;THG
	pop	di							;THG
	pop	si							;THG
	pop	dx							;THG
	pop	cx							;THG
	pop	bx							;THG
	pop	es							;THG
	pop	ds							;THG
	mov	sp,bp							;THG
	pop	bp							;THG
;THG
;THG	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp
;THG
		ret	8

KBDCHARIN	ENDP

_TEXT	ends
		END
