	TITLE	LLSCNFCN - Low Level Screen Function Support
;***
; LLSCNFCN - Low Level Screen Function Support
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;	This module has the following low level routines:
;	1. B$SWIDTH .... screen width support
;	2. B$SCREEN .... screen FUNCTION support
;	3. B$SETCLR .... color statement support
;	4. B$CSTATR .... Cursor support for LOCATE statement
;
;*****************************************************************************
	INCLUDE switch.inc
	INCLUDE rmacros.inc

	USESEG	_DATA
	USESEG	_BSS
	USESEG	CN_TEXT
	USESEG	RT_TEXT

	INCLUDE seg.inc
	INCLUDE oscalls.inc
	INCLUDE idmac.inc
	INCLUDE ibmunv.inc
	INCLUDE intmac.inc
	INCLUDE llgrp.inc

sBegin	_BSS

	globalW b$OldScrnBurst,,1	;old Screen Mode and burst
	staticW OldDim,,1		;old screen dimensions

	externB b$ScreenMode
	externB b$Burst
	externB b$ActPage
	externB b$ScrWidth
	externB b$ScrHeight
	externW	b$FBColors		; defined in llcgrp.asm
	externB	b$ForeColor		; defined in llcgrp.asm
	externB	b$NullColor		; defined in llcgrp.asm
	externB	b$CharColor		; defined in llcscn.asm
	externB	b$BorderColor		; border color (overscan)
	externW b$SetMode
	externW b$AlphaDim
	externW b$SetPages
	externW b$SetColor
	externW	b$SetAttr		

sEnd	_BSS


sBegin	_DATA

	externW b$CURSOR
	externW b$CSRTYP
	externB b$UsrCsrOn	; Is the cursor being displayed?
	externB b$UsrCsrStart	; user-defined cursor start line
	externB b$UsrCsrStop	; user-defined cursor stop line
	externB b$InsCsrStop	; insert cursor stop line

sEnd	_DATA



sBegin	RT_TEXT
	externNP B$FixTextPage	
	externNP B$ChkMonitor	; set VGA mono/color monitor

sEnd	RT_TEXT


sBegin	CN_TEXT
	assumes CS,CN_TEXT

	externNP B$SCNCLR
	externNP B$CSRDSP	;Display cursor
	externNP B$OFFCSR	;Turn off cursor
	externNP B$SCINIT
	externNP B$SCNSWI
	externNP B$ScreenN	;Initialize screen mode AL

;***
; B$SWIDTH - support for WIDTH statement
;OEM-interface routine
;
;Purpose:
;	This routine supports the width statement by attempting to set
;	the screen dimensions to those specified.  This routine is called
;	only if a change in the number of lines or columns is needed.
;
;	If the parameters are legal, the following must occur:
;	1.) Set hardware to reflect new conditions.
;	2.) Update OEM state variables.
;	3.) Call B$SCNSWI to inform runtime of dimension changes.
;	4.) Call B$SCNCLR to initialize screen, viewport, and cursor.
;	5.) Clear the screen (OS/2 only) (Call B$CLRSCN with a parameter of 0)
;
;	NOTE: If delayed screen initialization is being supported,
;	      B$SCNINIT must be called before any changes are made.
;
;Entry:
;	AL = prospective number of columns
;	CL = prospective number of lines
;
;Exit:
;	PSW.C = set to indicate error
;	PSW.C = reset to indicate update completed
;
;Uses:
;	Per convention
;
;Exceptions:
;	None.
;****

cProc	B$SWIDTH,<PUBLIC,NEAR>
cBegin
	CALL	B$SCINIT	;init screen if not already done
	mov	dl,b$ScrWidth	;get old width and height
	mov	dh,b$ScrHeight
	mov	OldDim,dx	;save for later restorations
	mov	bh,b$Burst	;get burst
	mov	bl,b$ScreenMode    ;get screen mode
	mov	b$OldScrnBurst,bx ;save old values for later
	xchg	bl,al		;bl=columns
	xchg	bh,cl		;bh=lines
	cmp	bl,dl		;width change?
	jne	DimChg		;go if so
	cmp	bh,dh		;height change?
	je	WidthExit	;go if not
DimChg:
	push	bx		;save dimensions
	call	[b$AlphaDim]	;change to new dimensions
	pop	cx
	jc	WidthError	;go if errors
	cmp	al,-1		;width satisfied
	je	WidthMode	;go setup mode if so
	;this mode suggested trying another for these dimensions
	mov	ah,b$Burst	;setup burst for B$ScreenN
	cmp	al,b$ScreenMode ;going to a different mode?
	je	NoBstChg	;leave burst alone if not
	xor	ah,ah		;clear burst
	cmp	al,ah		;going to mode 0?
	jne	NoBstChg	;go if not, with burst = 0 for modes > 0
	inc	ah		;burst = 1 for mode 0
NoBstChg:			
	call	C_ScreenN	; try that one (save colors)
	jc	WidthError	;go if error

	xchg	bx,cx		;width/height to BX
	cmp	bh,b$ScrHeight ;different height?
	jne	DimChg		;go if so
	cmp	bl,b$ScrWidth	;diferent width?
	jne	DimChg		;go if so

WidthMode:
	call	B$ChkMonitor	; Set VGA monitor type before setting mode
	call	[b$SetMode]	;set the actual mode
	mov	al,b$ScrWidth
	mov	cl,b$ScrHeight
	cCALL	B$SCNSWI	;Inform Hi-Level about dimensions change
	CALL	B$SCNCLR	; initialize the screen (homes cursor, etc.)
	call	B$FixTextPage	
	xor	ax,ax		;clear both pages
	call	[b$SetPages]	;set current page data
	clc			;no error
	JMP	SHORT WidthExit

WidthError:
	mov	cx,OldDim	; restore old screen mode data
	mov	ax,b$OldScrnBurst
	call	C_ScreenN	; reset mode-dependent data (save colors)
	xchg	bx,cx		; width/height to BX
	call	[b$AlphaDim]	; reset text dimensions
	call	B$FixTextPage	
	STC			; return with error
WidthExit:
cEnd

;*** 
;C_ScreenN - Save colors and call B$ScreenN
;
;Purpose:
;	Preserve Colors over call to B$Screen.  Can only be used if
;	the actual screen mode is not changing.  (just dimensions)
;
;Entry:
;	AX = Screen mode and burst
;	CX = Screen Dimensions
;
;Exit:
;	PSW.C set indicates error in B$ScreenN.
;
;Uses:
;	Per convention.
;
;Preserves:
;	CX.
;
;******************************************************************************
cProc	C_ScreenN,<NEAR>,<CX> ; entire routine
cBegin
	MOV	BH,[b$BorderColor] ; save colors
	MOV	BL,[b$NullColor]
	MOV	DL,[b$CharColor]
	PUSH	[b$FBColors]
	CALL	B$ScreenN	; AX = mode & burst (preserves AX,BX,CX,DX)
	POP	[b$FBColors]	; restore colors
	MOV	[b$CharColor],DL
	MOV	[b$NullColor],BL
	MOV	[b$BorderColor],BH
	MOV	AL,[b$ForeColor]
	PUSHF			; save PSW.C
	CALL	[b$SetAttr]	; ignore error return
	POPF			; restore error status from B$ScreenN
cEnd

;***
;B$SCREEN - SCREEN function support
;OEM-interface routine
;
;Purpose:
;	This routine provides OEM dependent support for the SCREEN function
;	by returning the character and its encoded attributes at a specified
;	position on the screen.	For the IBM-PC the attributes are encoded
;	as follows:
;
;		1. bits 0-3 contain the foreground color of the character
;		2. bits 4-6 contain the background color of the character
;		3. bit 7 contains the blinking attribute
;
;	The value returned for the encoded attributes should conform
;	to your machine's standard, as this is the value that is passed
;	back to the user.  The coordinates are guaranteed to be legal
;	for the current screen mode.
;
;	For systems with a hardware character generator, this routine
;	can act directly upon the CRT RAM.  Systems that have software
;	character generation and that do not have two byte characters
;	may have a separate buffer or may reverse translate the
;	characters from the video RAM.	For systems that have software
;	character generation and support two byte character codes, a
;	separate buffer or some other data structure must be maintained
;	so that two byte characters can be read from the "screen".
;
;	If the current screen mode support double byte characters,
;	it is possible that this routine will ask for the value
;	of either half of the character.
;
;	For FL_JAPAN, B$SCREEN should return the value of the entire
;	character (as defined for B$SCROUT). The OEM Independent code
;	will negate the MS-Continuous code for the character if it is
;	the second half of a double byte character.  All other
;	OEMs should return for a character code the value that
;	they want the SCREEN() function to return to the user.	No
;	further mapping or manipulation will be done for it.
;
;	NOTE: If you are supporting delayed screen initialization,
;	      B$SCNINIT has to be called before any attempt to read
;	      from the screen.
;
;Entry:
;	DH = requested column position (1-relative)
;	DL = requested row position (1-relative)
;
;Exit:
;	AX = character			(as defined for B$SCROUT)
;	BX = encoded attributes		(Hi-byte = 0)
;	PSW.C = set if we tried to read the middle of a double byte
;		character
;	PSW.C = reset in all other cases
;
;Uses:
;	Per convention
;
;Exceptions:
;	None
;****
;ALGORITHM:
;
;	save current cursor type
;	move cursor to requested position
;	read character &attributes at that position
;	replace cursor to original position and type
;

cProc	B$SCREEN,<PUBLIC,NEAR>,<SI>
cBegin

	CALL	B$SCINIT	;init screen if not already done

	MOV	CX,b$CSRTYP	; save current cursor type in CX
	CALL	B$OFFCSR	; position invisible cursor at (DH,DL)
	MOV	BH,b$ActPage	; get active display page

	SCNIO	vReadChar	;read encoded attributes at current csr position

	OR	AL,AL		; vReadChar returns NULL in graphics modes
	JNZ	NOT_NULL	;  if no char is present in char cell
	MOV	AL,' '		; so we must compensate here
NOT_NULL:			
	XOR	BX,BX		; zero BX
	XCHG	AH,BL		; BX = Attribute
	XCHG	AX,CX		; AX = b$CSRTYP (Old)
				; CX = Character
	MOV	DX,b$CURSOR	; get original cursor position
	CALL	B$CSRDSP	; restore original cursor position and type

	XOR	CH,CH		; Set Hi Byte zero
	XCHG	AX,CX		; AX = Character


cEnd


;***
;B$SETCLR - COLOR statement support
;OEM-interface routine
;
;Purpose:
;	This routine provides support for the COLOR statement.
;	The parameters to this function are implementation and
;	screen mode dependent.	For all machines, the first
;	parameter is the ForeGround Color and the second parameter
;	is the Border Color.  If it is desired to indicate an
;	error from this routine (such as wrong number of parameters,
;	parameter out of range, etc), return with PSW.C set.
;
;	If delayed screen initialization is being supported,
;	the routine B$SCNINT must be called before any
;	changes are made.
;
;Entry:
;	[SI] = address of the high end of the parameter list
;	       (parameters run from high to low memory).
;	[CX] = count of words in parameter list
;
;	This list is in the format for B$GetParm to parse.
;
;Exit:
;	PSW.C = set indicates that an error was encountered
;
;Uses:
;	Per convention
;
;Exceptions:
;	None.
;****
;	Since the meaning and number of parameters for the COLOR
;	statement is dependent on the screen mode, this routine
;	just calls the mode-dependent routine and hands off the
;	parameters entirely.
;

cProc	B$SETCLR,<PUBLIC,NEAR>
cBegin
	CALL	B$SCINIT	; init screen if not already done
	call	[b$SetColor]	; call mode-dependent module
cEnd

;***
;B$CSRATR - Set cursor attribute
;OEM-interface routine
;
;Purpose:
;	This routine handles a request to set the cursor attribute of
;	the user cursor.  There are three cursor attribute bytes.  They
;	correspond to parameters three, four, and five of the LOCATE
;	statement.
;
;	These parameters are:
;
;	  3.  cursor - is a value indicating whether the cursor is
;		       visible or not. 0 (zero) for off, 1 (one) for
;		       on.
;	  4.  start  - is the cursor starting scan line. Must be in
;		       the range [0,31].
;	  5.  stop   - is the cursor stop scan line.  Must be in the
;		       range [0,31].
;
;	B$SCRATR must check the start and stop values to make sure that
;	they are in the range [0,31].  If they are not in that range,
;	return with PSW.C set to indicate an error.  If these values are
;	legal, but will produce unusual results when the cursor is set
;	to them (i.e. the cursor is invisible or split), the cursor
;	should be updated anyway.  After all, the user asked for it.
;	Note that changing the stop line of the user cursor will also
;	change the stop line of the insert cursor to the same value.
;
;Entry:
;	[AH] - LOCATE parameter 3 existence flag
;		(0 iff the user specified no value)
;	[AL] - LOCATE parameter 3 value
;	[BH] - LOCATE parameter 4 existence flag
;	       (0 iff the user specified no value)
;	[BL] - LOCATE parameter 4 value
;	[CH] - LOCATE parameter 5 existence flag
;	       (0 iff the user specified no value)
;	[CL] - LOCATE parameter 5 value
;
;Exit:
;	PSW.C - set indicates a cursor attribute parameter error
;
;Uses:
;	Per convention
;
;Exceptions:
;	None.
;****
;Algorithm:
;	if param 3 exists then
;	  if in valid range then store cursor toggle
;	    else error
;	if param 4 exists then
;	    if in valid range then
;		update user cursor start line
;		if param 5 exists then
;		    if in valid range then
;			update user cursor stop line
;			update insert cursor stop line
;		      else error
;		  else
;		    update user cursor stop line := user cursor start line
;		    update insert cursor stop line := user cursor start line
;	   else
;	     if param 5 exists then error
;Modified:
;	b$InsCsrTyp - insert mode cursor attributes possibly changed
;	b$UsrCsrTyp - user mode cursor attributes possibly changed
;
;#**

cProc	B$CSRATR,<PUBLIC,NEAR>
cBegin

	OR	AH,AH		;see if value is given for cursor toggle
	JZ	CSR4TH		;br. if no value is given
	CMP	AL,1		;check valid range [0,1]
	JA	CATRER		;br. if out of range error
	MOV	B$UsrCsrOn,AL	;store cursor toggle
CSR4TH:
	OR	BH,BH		;see if value is given for cursor start line
	JZ	CSR5TH		;br. if no value is given
	CMP	BL,31D		;check valid range [0,31]
	JA	CATRER		;br. if out of range error
	MOV	b$UsrCsrStart,BL ;store startline for user cursor

	OR	CH,CH		;see if value is given for cursor stop line
	JZ	NO5VAL		;br. if no value is given
	CMP	CL,31D		;check valid range [0,31]
	JA	CATRER		;br. if out of range error
	MOV	b$InsCsrStop,CL ; store insert cursor stop line
	MOV	b$UsrCsrStop,CL ; store user cursor stop line
	JMP	SHORT CSRDON	; valid return
NO5VAL:
	MOV	b$InsCsrStop,BL ;default insert csr stop line = stop line
	MOV	b$UsrCsrStop,BL ;default user csr stop line = stop line
CSR5TH: 			;no value was given for cursor start line
	OR	CH,CH		;see if value was given for cursor stop line
	JNZ	CATRER		;error if stop value given without start value
CSRDON:
	CLC			;clear flag for valid return
	RET
CATRER:
	STC			;set flag for parameter error
cEnd

sEnd	CN_TEXT

	END
