; Note:
; Strangely  enough,  on  some  machines the cursor still appears in the
; middle  of  the line on program exit. Darned IBM BIOS.  I really don't
; know  who  wrote  this  piece  of  s...  In  any  case,  this is a bug
; apparently  peculiar to some machines, which you have to fix yourself.
; grep for int 10h in *.ASM.

PUBLIC  FSCREEN

EXTRN	WindowStartline:Word
	
;---------------------------------------------------------------------------
Title Screen-builder

	; This updates a screen. It can build it from a given buffer
	; position in a window ( given by Buffer Start and Buffer End ).
	; NOTE: The speed of this function is absolutely crucial for
	; satisfactory results.




Program SEGMENT Para	PUBLIC  'code'
	ASSUME  CS:PROGRAM, DS:PROGRAM, ES:PROGRAM, SS:PROGRAM

Comment $

	Screen-start	ES:DI   Passed  DI
	Screen-end		Passed  DX
	File-start	DS:SI   Passed  SI

	File-cursor	DS:VAR  Global
	Marker-array	DS:VAR  Global
	Region-end	DS:VAR  Global

	File-end	DS:VAR  Returned

	AX	[Accu]
	BX	Real row
	CX	~
	 CH	Colorbyte
	 CL	[Column]	( can be gotten through BCB )
	DX	Screen_end	( passed )

	SI	DS: Sourceindex to Buffer	( passed-could be gotten from BCB )
	DI	ES: Index to Screen	( passed )

	BP	[End of File]
$

;------------------------Screen Macroes-----------------------------------
Include FDef.Def

; if mono or flicker ( not noflicker )
	stoschar	MACRO
		stosw
		ENDM

if noflicker
	stoschar	MACRO
		call	colorout
	ENDM
endif


Reg_end_char	EQU	'<'	
Wraparoundchar  EQU	'!'
maxcolumn	EQU	79d

Initialize_Variables	MACRO
		mov	AX, Screensegment
		mov	ES, AX
		mov	BP, DS:BCB.Fend ; load BX with the end of file ptr
		inc	BP		; for the cursor...
		xor	BX, BX
		xor	CL, CL
		xor	CH, CH		; holds line number
		cld
	ENDM


Set_Cursor	MACRO
			mov	DS:BCB.ScrCursor, DI
			push	SI
			push	DI
			push	AX
			push	BX
			push	DX
			push	CX
			push	BP

			mov	AH, 2		; set cursor position
			mov	BH, 0
			mov	DX, CX
			xchg	DH, DL
			add	DX, CS:WindowStartLine
			xchg	DH, DL
			int	10h		; request new cursor

			pop	BP
			pop	CX
			pop	DX
			pop	BX
			pop	AX
			pop	DI
			pop	SI
	ENDM

;*****************************START***************************************
; This routine handles everything after the end of the file is encountered.
; Since there is nothing that can happen afterwards, this is just a faster
; special handle of the normal procedure

Special_EOF	PROC	NEAR

		mov	AL, EOF_Char	; this is a small dot
		mov	AH, LowIntensity
		mov	SI, 0FFFFh	; signals we won't reach last char on
					; screen


SE1:		cmp	DI, DX		; have we reached the window's end ?
		jb	SE2
		jmp	Exit_routine	; yes, so quit

SE2:		stoschar			; no, so output the EOF character
		jmp	SE1

Special_EOF	ENDP
;***************************************************************************
Exit_routine:   dec	SI
		mov	DS:BCB.Scrend, SI	; SI-1 is the last character
						; on the scr
		mov	ES:[Modelinestart], ModeLinecolor*256+' '
						; small bug-fix
		ret



;***************************************************************************
FScreen PROC NEAR

		Initialize_Variables

Start:		cmp	DI, DX			; did we reach the screenend ?
		jae	Exit_routine

EOF_Q:		cmp	SI, BP			; did we reach the fileend ?
		jae	Special_EOF		; [special exception handling]

Get_char:	mov	AL, DS:[SI]		; get a character from the
		mov	AH, nocolor		; file

		cmp	CL, Byte Ptr maxcolumn	; are we at last screencolumn?
		jb	Get_Char1

			call	Wrap		; then postpone this char and
						; put up the wraparound char

Get_Char1:	cmp	SI, DS:BCB.Fcursor	; is this the cursor position?
		jne	no_cursor0

			Set_Cursor		; yes, so set it

no_cursor0:	cmp	AL, 32			; is this a ^* character
		jae	Get_Char2

			call	ControlChar	; handle the special character

Get_Char2:	stoschar				; normal character -> put it
		inc	BX			; to screen.
		inc	CL
		inc	SI

		jmp	Start


;---------------------------------------------------------------------------
Wrap:		cmp	AL, LF			; if we are at a LF, this is
		je	NoWrap			; not a wrap, but an EOLN
		inc	CH			; after real output now:
		xor	CL, CL			; col / row

		push	AX			; remember the real character
		mov	AX, Wraparoundchar	; output the wraparoundchar
		mov	AH, LowIntensity
		stoschar
		pop	AX

NoWrap:		ret				; and continue logical line

FScreen ENDP
;---------------------------------------------------------------------------
	; This handles all characters in the file that are smaller than
	; a SPACE ( i.e. controlcharacters ).
ControlChar	PROC	NEAR
if tab8spaces
	cmp	AL, 9				; TAB is 8 spaces
	je	ControlChar1
endif
	cmp	AL, LF				; LF means don't advance BX
	je	ControlLFret
	cmp	AL, CR				; CR means don't put a ^M
	je	ControlCRret
	cmp	AL, 1Ah				; EOF means special character
	je	ControlEOFret

	cmp	CL, Byte Ptr MaxColumn		; other control character
	jb	CC111				; means two chars w/ ^*
		call	Wrap			; if necessary

CC111:	push	AX				; put up the ^
	mov	AX, lowintensity*256+'^'
	stoschar
	pop	AX
	add	AL, '@'				; adjust to ASCII
	inc	CL
	cmp	CL, Byte Ptr maxcolumn		; are we at last column ?
	jae	Wrap				; if necessary

	ret

;---------------------------------------------------------------------------
	; this handles the TAB

ControlChar1:
	push	AX
	push	DX

	mov	DX, BX
	mov	DH, DL
	and	DH, 7
	mov	DL, 8
	sub	DL, DH

if color	; in color, we have to place the cursor on a visible
		; character
	mov	AX, ' '+nocolor*256		; and output n tabs
endif
if mono
	mov	ax, '	'+nodisplay*256
endif

CCC1:	dec	DL
	jz	CCCOut
	stoschar
	inc	BX
	inc	CL
if color
	mov	ax, '	'+nodisplay*256
endif
	cmp	CL, Maxcolumn
	jb	CCC1
	call	Wrap
	jmp	CCC1

CCCOut:	pop	DX
	pop	AX
	mov	AL, ' '
	ret

;---------------------------------------------------------------------------
	; This handles the rest of the line after a LF
ControlLFret:
	mov	AH, nodisplay

CLF0:	cmp	CL, Maxcolumn
	jae	CLF1
	inc	CL
	stoschar
	jmp	CLF0

CLF1:	mov	AX, '<'+lowintensity*256
	stoschar
	pop	AX				; get rid of returnaddress
	xor	CL, CL				; we start anew at another ln
	xor	BX, BX
	inc	CH
	inc	SI
	jmp	Start

	ret

;---------------------------------------------------------------------------
	; This simply displays no character at a CR or EOF
ControlCRret:
ControlEOFret:
	mov	AH, nodisplay
if color					; put cursor on display
	mov	ax, ' '+256*nocolor
endif
	ret


ControlCHAR	ENDP

if noflicker
colorout	proc	near
		push	dx
		mov	dx, 3dah
		push	ax
	Wait:	in	al, dx
		test	al, 8
		jz	Wait
		pop	ax
		stosw
		pop	dx
		ret
colorout	endp
endif

PROGRAM ENDS
	END
