;       SCCSID = @(#)kbdsets.asm	6.1 91/02/15
;	SCCSID = @(#)kbdsets.asm	6.3 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
	Page	60,132

;	Modification History
;
;	13-Aug-86 (billme) swap order of tests for echo mask and input mask
;	to match Dos 5 (dos 5 tests echo first, then input)
;
;	14-Aug-86 (billme) check for raw/noecho mode and cooked/echo mode
;	and set appropriately
;
;	19-Aug-86 (billme): change to new scheme (see kbdstrng.asm)
;
;	09-Sep-86 (billme): change code to set raw/cooked/echo/noecho
;	only as requested ... also, add precise checking to insure
;	status to set is exactly correct (e.g. noecho/cooked is not allowed)
;
;	02-Oct-86 (billme): swap order of error check for INPUT_MASK
;	and ECHO_MASK for compatibility with DOS 5.
;
;	18-Oct-86 (karlsc): Fixed StatusFlag logic. Needed to chaff out null
;	parameters (they are legal).
;
;	18-Nov-86 (billme): make input_mask/echo_mask checking as
;	compatible as possible with DOS 5 - fapi supports neither
;	"raw mode / echo on" nor "cooked mode / echo off"
;
;	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.
;
;
;/*************** START OF SPECIFICATIONS ******************************/
;/*								       */
;/* SUBROUTINE NAME:  KbdSetStatus				       */
;/*								       */
;/* DESCRIPTIVE NAME:  Set the characteristics of the keyboard.	       */
;/*								       */
;/* FUNCTION:  This function allows the user to request changes to the */
;/*	       behavior of the keyboard.			       */
;/*								       */
;/* NOTES:  Version 1.0 ignores changes to the TurnAround character,   */
;/*	    NLS shift state, and echo mode.			       */
;/*	    KbdHandle is ignored for Version 1.0.		       */
;/*								       */
;/* ENTRY POINT:						       */
;/*	    LINKAGE:  EXTRN KbdSetStatus:FAR			       */
;/*								       */
;/* INPUT:	      push@ OTHER Structure			       */
;/*		      push  WORD  KbdHandle			       */
;/*		      call  KbdSetStatus			       */
;/*								       */
;/* EXIT-NORMAL:  AX = 0					       */
;/*								       */
;/* EXIT-ERROR:	 AX = Error Code				       */
;/*								       */
;/* EFFECTS:							       */
;/*								       */
;/* INTERNAL REFERENCES:					       */
;/*    ROUTINES:						       */
;/*								       */
;/* EXTERNAL REFERENCES:					       */
;/*    ROUTINES:						       */
;/*								       */
;/*************** END OF SPECIFICATIONS ********************************/

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

	EXTRN	__api_begin:near
	EXTRN	__api_end:near
.list

KBDSTAT STRUC			; stack frame snap shot

		dw	?	; BP
		dw	?	; IP
		dw	?	; CS
		dw	?	; dummy keyboard handle (0)
	Buffer	dd	?	; Structure address

KBDSTAT ENDS


DSEG	SEGMENT BYTE	PUBLIC	'DATA'

DSEG	ENDS


	PUBLIC	KBDSETSTATUS


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

	EXTRN	StatusFlag:BYTE
	EXTRN	KbdType:BYTE	; cpd12 (p1082)


KBDSETSTATUS	PROC	FAR

	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
				; required to save: bp,ds,bx,cx

		lds	bx,[bp].Buffer		; DS:BX <- buffer address
		cmp	[bx].KbdStatLength,BUFFER_LEN	; user struc large enough?
		jae	Start			; yes

		mov	ax,ERROR_KBD_INVALID_LENGTH
		jmp	short KbdSetExit
Start:
		mov	cx,[bx].KbdStatMask	; CX <- mask
		or	cl,cl			; IF ( MASK == NoFunction)
		jz	KbdSetExitNoErr		;   THEN exit NO ERROR

		.erre	RAW_NOECHO  EQ	00000110b
		.erre	COOKED_ECHO EQ	00001001b
		.erre	RAWCOOKED   EQ	00001100b
		.erre	ECHOONOFF   EQ	00000011b

		; if echo/input mask is
		;
		;   lowest 2 bits on	=> invalid echo mask
		;   == 5 or > 9		=> invalid input mask

		mov	ch,cl			; save mask in CH
		and	cl,0Fh			; ignore high nibble

		mov	ax,ERROR_KBD_INVALID_ECHO_MASK
		inc	cl
		and	cl,3
		jz	KbdSetExit

		mov	ax,ERROR_KBD_INVALID_INPUT_MASK
		mov	cl,ch			; recover original mask @@
		and	cl,0Fh			; ignore high nibble @@

		cmp	cl,9			; @@ use cl
		ja	KbdSetExit
		cmp	cl,5			; @@ use cl
		je	KbdSetExit

CheckShiftState:
		test	ch,00010000b		; shift state to be modified?
		jz	ChkRawCooked		; no

		mov	bx,[bx].Shift_State	; (( last use of DS:BX ))
		mov	ax,BIOS_SEGMENT		; yes, alter BIOS shift state
		mov	ds,ax
		mov	WORD PTR ds:[KBDFLAG],bx
		mov	ah,1			; peek at the keyboard @@
		add	ah,cs:[KbdType]		; cpd12 (p1082)
		int	16h			; to update the led's  @@


ChkRawCooked:					; IF (status&RAWCOOKED == NULL)
		test	ch,RAWCOOKED		;   StatusFlag.RAWCOOKED is unchanged
		jz	ChkEchoOnOff
		and	cs:StatusFlag, NOT RAWCOOKED
ChkEchoOnOff:
		test	ch, ECHOONOFF		; IF ( status&ECHOONOFF == NULL)
		jz	SetStatusReg		;   StatusFlag.ECHOONOFF is unchanged
		and	cs:StatusFlag, NOT ECHOONOFF
SetStatusReg:
		and	ch,RAWCOOKED OR ECHOONOFF
		or	cs:StatusFlag,ch
KbdSetExitNoErr:
		xor	ax,ax			; return no error
KbdSetExit:

	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp

		ret	6			; clear stack frame

KBDSETSTATUS	ENDP

_TEXT	ends
	END
