CR	EQU	13			;Carriage return
LF	EQU	10			;Line feed

;-----------------------------------------------------------------------;
; This file contains procedures that move the cursor, as well as two	;
; procedures for clearing parts of the screen.				;
;									;
; CLEAR_SCREEN			Clear the entire screen			;
; GOTO_XY			Move the cursor to a new position	;
; CURSOR_RIGHT			Move the cursor right one column	;
; UPDATE_REAL_CURSOR		Move real cursor to virtual cursor posn	;
; UPDATE_VIRTUAL_CURSOR		Move virtual cursor to real cursor posn	;
; READ_CURSOR_POSITION		Get the current cursor position		;
; CLEAR_TO_END_OF_LINE		Clear all the line after the cursor	;
; SEND_CRLF			Move cursor to start of the next line	;
;-----------------------------------------------------------------------;

.MODEL	SMALL
.CODE

	PUBLIC	CLEAR_SCREEN
;-----------------------------------------------------------------------;
; This procedure clears the entire screen.				;
;-----------------------------------------------------------------------;
CLEAR_SCREEN	PROC
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	XOR	AL,AL			;Blank entire window
	XOR	CX,CX			;Upper left corner is at (0,0)
	MOV	DH,24			;Bottom line of screen is line 24
	MOV	DL,79			;Right side is at column 79
	MOV	BH,7			;Use normal attribute for blanks
	MOV	AH,6			;Call for SCROLL-UP function
	INT	10h			;Clear the window
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	RET
CLEAR_SCREEN	ENDP


	PUBLIC	GOTO_XY
.DATA
	EXTRN	SCREEN_PTR:WORD		;Pointer to character under cursor
	EXTRN	SCREEN_X:BYTE, SCREEN_Y:BYTE
.CODE
;-----------------------------------------------------------------------;
; This procedure moves the cursor					;
;									;
; On entry:	DH	Row (Y)						;
;		DL	Column (X)					;
;-----------------------------------------------------------------------;
GOTO_XY		PROC
	PUSH	AX
	PUSH	BX
	MOV	BH,0			;Display page 0
	MOV	AH,2			;Call for SET CURSOR POSITION
	INT	10h

	MOV	AL,DH			;Get the row number
	MOV	BL,80			;Multiply by 80 chars per line
	MUL	BL			;AX = row * 80
	ADD	AL,DL			;Add column
	ADC	AH,0			;AX = row * 80 + column
	SHL	AX,1			;Convert to a byte offset
	MOV	SCREEN_PTR,AX		;Save the cursor offset
	MOV	SCREEN_X,DL		;Save the cursor position
	MOV	SCREEN_Y,DH
	
	POP	BX
	POP	AX
	RET
GOTO_XY		ENDP

	PUBLIC	CURSOR_RIGHT
.DATA
	EXTRN	SCREEN_PTR:WORD		;Pointer to character under cursor
	EXTRN	SCREEN_X:BYTE, SCREEN_Y:BYTE
.CODE
;-----------------------------------------------------------------------;
; This procedure moves the cursor one position to the right or to the	;
; next line if the cursor was at the end of a line.			;
;									;
; Uses:		SEND_CRLF						;
; Writes:	SCREEN_PTR, SCREEN_X, SCREEN_Y				;
;-----------------------------------------------------------------------;
CURSOR_RIGHT	PROC
	INC	SCREEN_PTR		;Move to next character position (word)
	INC	SCREEN_PTR
	INC	SCREEN_X		;Move to next column
	CMP	SCREEN_X,79		;Make sure column <= 79
	JBE	OK
	CALL	SEND_CRLF		;Go to next line
OK:
	RET
CURSOR_RIGHT	ENDP

	PUBLIC	UPDATE_REAL_CURSOR
;-----------------------------------------------------------------------;
; This procedure moves the real cursor to the current virtual cursor	;
; position.  You'll want to call it just before you wait for keyboard	;
; input.								;
;-----------------------------------------------------------------------;
UPDATE_REAL_CURSOR	PROC
	PUSH	DX
	MOV	DL,SCREEN_X		;Get position of the virtual cursor
	MOV	DH,SCREEN_Y
	CALL	GOTO_XY			;Move real cursor to this position
	POP	DX
	RET
UPDATE_REAL_CURSOR	ENDP


	PUBLIC	UPDATE_VIRTUAL_CURSOR
;-----------------------------------------------------------------------;
; This procedure updates the position of our virtual cursor to agree	;
; with the position of the real cursor.					;
;-----------------------------------------------------------------------;
UPDATE_VIRTUAL_CURSOR	PROC
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	MOV	AH,3			;Ask for the cursor position
	XOR	BH,BH			;On page 0
	INT	10h			;Get cursor position into DH, DL
	CALL	GOTO_XY			;Move virtual cursor to this position
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	RET
UPDATE_VIRTUAL_CURSOR	ENDP


	PUBLIC	READ_CURSOR_POSITION
;-----------------------------------------------------------------------;
; This procedure doesn't follow the conventions for returning		;
; information in the AX register so that it can be used easily with	;
; GOTO_XY.								;
;									;
; Returns:	DH,DL	Row, column of cursor				;
;-----------------------------------------------------------------------;
READ_CURSOR_POSITION	PROC
	PUSH	AX
	PUSH	BX
	PUSH	CX
	MOV	AH,3			;Ask for current cursor position
	MOV	BH,0			;On page 0
	INT	10h			;Return information in DX
	POP	CX
	POP	BX
	POP	AX
	RET
READ_CURSOR_POSITION	ENDP


	PUBLIC	CLEAR_TO_END_OF_LINE
;-----------------------------------------------------------------------;
; This procedure clears the line from the current cursor position to	;
; the end of that line.							;
;-----------------------------------------------------------------------;
CLEAR_TO_END_OF_LINE	PROC
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	MOV	DL,SCREEN_X
	MOV	DH,SCREEN_Y
	MOV	AH,6			;Set up to clear to end of line
	XOR	AL,AL			;Clear window
	MOV	CH,DH			;All on same line
	MOV	CL,DL			;Start at the cursor position
	MOV	DL,79			;And stop at the end of the line
	MOV	BH,7			;Use normal attribute
	INT	10h
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	RET
CLEAR_TO_END_OF_LINE	ENDP


	PUBLIC	SEND_CRLF
;-----------------------------------------------------------------------;
; This routine just sends a carriage return-line feed pair to the	;
; display, using the DOS routines so that scrolling will be handled	;
; correctly.								;
;									;
; Uses:		UPDATE_VIRTUAL_CURSOR					;
;-----------------------------------------------------------------------;
SEND_CRLF	PROC
	PUSH	AX
	PUSH	DX
	MOV	AH,2
	MOV	DL,CR
	INT	21h
	MOV	DL,LF
	INT	21h
	CALL	UPDATE_VIRTUAL_CURSOR	;Update position of virtual cursor
	POP	DX
	POP	AX
	RET
SEND_CRLF	ENDP


	END
