.MODEL	SMALL


;-----------------------------------------------------------------------;
; This file contains procedures for displaying sectors on the screen:	;
;									;
; INIT_SEC_DISP			Reads a sector and redraws the screen	;
; WRITE_HEADER			Writes the header on the screen		;
; WRITE_TOP_HEX_NUMBERS		Writes numbers along the top of the box	;
; DISP_HALF_SECTOR		Displays half of the sector		;
; DISP_LINE			Displays one line of the sector		;
; WRITE_PROMPT_LINE		Writes the prompt line to the screen	;
; WRITE_FUNCTION_KEYS		Display the function-key line		;
;-----------------------------------------------------------------------;


;-----------------------------------------------------------------------;
; Graphics characters for border of sector.				;
;-----------------------------------------------------------------------;
VERTICAL_BAR	EQU	0BAh
HORIZONTAL_BAR	EQU	0CDh
UPPER_LEFT	EQU	0C9h
UPPER_RIGHT	EQU	0BBh
LOWER_LEFT	EQU	0C8h
LOWER_RIGHT	EQU	0BCh
TOP_T_BAR	EQU	0CBh
BOTTOM_T_BAR	EQU	0CAh
TOP_TICK	EQU	0D1h
BOTTOM_TICK	EQU	0CFh


.DATA

TOP_LINE_PATTERN	LABEL	BYTE
	DB	' ',7
	DB	UPPER_LEFT, 1
	DB	HORIZONTAL_BAR,12
	DB	TOP_TICK,1
	DB	HORIZONTAL_BAR,11
	DB	TOP_TICK,1
	DB	HORIZONTAL_BAR,11
	DB	TOP_TICK,1
	DB	HORIZONTAL_BAR,12
	DB	TOP_T_BAR,1
	DB	HORIZONTAL_BAR,18
	DB	UPPER_RIGHT,1
	DB	0
BOTTOM_LINE_PATTERN	LABEL	BYTE
	DB	' ',7
	DB	LOWER_LEFT, 1
	DB	HORIZONTAL_BAR,12
	DB	BOTTOM_TICK,1
	DB	HORIZONTAL_BAR,11
	DB	BOTTOM_TICK,1
	DB	HORIZONTAL_BAR,11
	DB	BOTTOM_TICK,1
	DB	HORIZONTAL_BAR,12
	DB	BOTTOM_T_BAR,1
	DB	HORIZONTAL_BAR,18
	DB	LOWER_RIGHT,1
	DB	0

.DATA?

	EXTRN	SECTOR:BYTE

.CODE

	PUBLIC	INIT_SEC_DISP
	EXTRN	READ_SECTOR:PROC
	EXTRN	WRITE_PATTERN:PROC, SEND_CRLF:PROC
	EXTRN	GOTO_XY:PROC, WRITE_PHANTOM:PROC
.DATA
	EXTRN	LINES_BEFORE_SECTOR:BYTE
	EXTRN	SECTOR_OFFSET:WORD
.CODE
;-----------------------------------------------------------------------;
; This procedure initializes the half-sector display.			;
;									;
; Uses:		WRITE_PATTERN, SEND_CRLF, DISP_HALF_SECTOR		;
;		WRITE_TOP_HEX_NUMBERS, GOTO_XY, WRITE_PHANTOM		;
; Reads:	TOP_LINE_PATTERN, BOTTOM_LINE_PATTERN			;
;		LINES_BEFORE_SECTOR					;
; Writes:	SECTOR_OFFSET						;
;-----------------------------------------------------------------------;
INIT_SEC_DISP	PROC
	PUSH	DX
	CALL	WRITE_HEADER		;Write the new header
	CALL	READ_SECTOR		;Read in the disk sector

	XOR	DL,DL			;Move cursor into position at start
	MOV	DH,LINES_BEFORE_SECTOR	; of the 3rd lines
	CALL	GOTO_XY			;Move the cursor
	CALL	WRITE_TOP_HEX_NUMBERS	;Write line of numbers along the top
	LEA	DX,TOP_LINE_PATTERN	;Display the top line of the box
	CALL	WRITE_PATTERN
	CALL	SEND_CRLF		;Move to the next line

	XOR	DX,DX			;Start at the beginning of the sector
	MOV	SECTOR_OFFSET,DX	;Set sector offset to 0
	CALL	DISP_HALF_SECTOR	;Display the first half sector
	LEA	DX,BOTTOM_LINE_PATTERN	;Display the bottom of the box
	CALL	WRITE_PATTERN
	CALL	WRITE_PHANTOM		;Display the phantom cursor
	POP	DX
	RET
INIT_SEC_DISP	ENDP


	PUBLIC	WRITE_HEADER
.DATA
	EXTRN	HEADER_LINE_NO:BYTE
	EXTRN	HEADER_PART_1:BYTE
	EXTRN	HEADER_PART_2:BYTE
	EXTRN	DISK_DRIVE_NO:BYTE
	EXTRN	CURRENT_SECTOR_NO:WORD
	EXTRN	FILE_FLAG:BYTE
	EXTRN	FILE_HEADER:BYTE
	EXTRN	FILE_NAME:BYTE
.CODE
	EXTRN	GOTO_XY:PROC, CLEAR_TO_END_OF_LINE:PROC
	EXTRN	WRITE_DECIMAL:PROC
;-----------------------------------------------------------------------;
;  This procedure writes the header with disk drive and sector number.	;
;									;
; Uses:		GOTO_XY, WRITE_STRING, WRITE_CHAR, WRITE_DECIMAL	;
;		CLEAR_TO_END_OF_LINE					;
; Reads:	HEADER_LINE_NO, HEADER_PART_1, HEADER_PART_2		;
;		DISK_DRIVE_NO, CURRENT_SECTOR_NO, FILE_FLAG		;
;		FILE_HEADER, FILE_NAME					;
;-----------------------------------------------------------------------;
WRITE_HEADER	PROC
	PUSH	DX
	XOR	DL,DL			;Move cursor to header line number
	MOV	DH,HEADER_LINE_NO
	CALL	GOTO_XY

	CMP	FILE_FLAG,1		;Are we in file mode?
	JE	WRITE_OFFSET		;Yes, then don't write drive number
	LEA	DX,HEADER_PART_1	;Display "Disk "
	CALL	WRITE_STRING
	MOV	DL,DISK_DRIVE_NO	;Display the disk drive number
	ADD	DL,'A'			;Print drives A, B, ...
	CALL	WRITE_CHAR
WRITE_OFFSET:
	LEA	DX,HEADER_PART_2	;Display "     Sector "
	CALL	WRITE_STRING
	MOV	DX,CURRENT_SECTOR_NO	;Display the sector number
	CALL	WRITE_DECIMAL
	CMP	FILE_FLAG,1		;Are we in file mode?
	JNE	DONT_WRITE_FILE_HEADER	;No, then don't write the file header
	LEA	DX,FILE_HEADER		;Yes, display the file header
	CALL	WRITE_STRING
	LEA	DX,FILE_NAME		;Write the name of the file
	CALL	WRITE_STRING
DONT_WRITE_FILE_HEADER:
	CALL	CLEAR_TO_END_OF_LINE	;Clear rest of sector number
	POP	DX
	RET
WRITE_HEADER	ENDP


	EXTRN	WRITE_CHAR_N_TIMES:PROC, WRITE_HEX:PROC, WRITE_CHAR:PROC
	EXTRN	WRITE_HEX_DIGIT:PROC, SEND_CRLF:PROC
;-----------------------------------------------------------------------;
; This procedure writes the index numbers (0 through F) at the top of	;
; the half-sector display.						;
;									;
; Uses:		WRITE_CHAR_N_TIMES, WRITE_HEX, WRITE_CHAR		;
;		WRITE_HEX_DIGIT, SEND_CRLF				;
;-----------------------------------------------------------------------;
WRITE_TOP_HEX_NUMBERS	PROC
	PUSH	CX
	PUSH	DX
	MOV	DL,' '			;Write 9 spaces for left side
	MOV	CX,9
	CALL	WRITE_CHAR_N_TIMES
	XOR	DH,DH			;Start with 0
HEX_NUMBER_LOOP:
	MOV	DL,DH
	CALL	WRITE_HEX		;Write a two-digit hex number
	MOV	DL,' '
	CALL	WRITE_CHAR		;Write a space between numbers
	INC	DH			;Increment the number
	CMP	DH,10h			;Have we written 16 numbers?
	JB	HEX_NUMBER_LOOP		;No, keep writing

	MOV	DL,' '			;Write hex numbers over ASCII window
	MOV	CX,2
	CALL	WRITE_CHAR_N_TIMES
	XOR	DL,DL			;Start over at zero again

HEX_DIGIT_LOOP:
	CALL	WRITE_HEX_DIGIT		;Write a single-digit hex number
	INC	DL			;Increment the number
	CMP	DL,10h			;Have we written 16 numbers?
	JB	HEX_DIGIT_LOOP		;No, keep writing

	CALL	SEND_CRLF		;Move to the start of the next line
	POP	DX
	POP	CX
	RET
WRITE_TOP_HEX_NUMBERS	ENDP


	PUBLIC	DISP_HALF_SECTOR
	EXTRN	SEND_CRLF:PROC
;-----------------------------------------------------------------------;
; This procedure displays half a sector (256 bytes)			;
;									;
; On entry:	DS:DX	Offset into sector, in bytes -- should be	;
;			multiple of 16.					;
;									;
; Uses:		DISP_LINE, SEND_CRLF					;
;-----------------------------------------------------------------------;
DISP_HALF_SECTOR	PROC
	PUSH	CX
	PUSH	DX
	MOV	CX,16			;Display 16 lines
HALF_SECTOR:
	CALL	DISP_LINE		;Display a single line
	CALL	SEND_CRLF		;Move to the start of the next line
	ADD	DX,16			;Increase our offset by 16 bytes
	LOOP	HALF_SECTOR		;Keep writing for 16 lines
	POP	DX
	POP	CX
	RET
DISP_HALF_SECTOR	ENDP


	PUBLIC	DISP_LINE
	EXTRN	WRITE_HEX:PROC
	EXTRN	WRITE_CHAR:PROC
	EXTRN	WRITE_CHAR_N_TIMES:PROC
;-----------------------------------------------------------------------;
; This procedure displays one line of data, or 16 bytes, first in hex,	;
; then in ASCII.							;
;									;
; On entry:	DS:DX	Offset into sector, in bytes.			;
;									;
; Uses:		WRITE_CHAR, WRITE_HEX, WRITE_CHAR_N_TIMES		;
; Reads:	SECTOR							;
;-----------------------------------------------------------------------;
DISP_LINE	PROC
	PUSH	BX
	PUSH	CX
	PUSH	DX
	MOV	BX,DX			;Offset is more useful in BX
	MOV	DL,' '
	MOV	CX,3			;Write 3 spaces before line
	CALL	WRITE_CHAR_N_TIMES
					;Write offset in hex
	CMP	BX,100h			;Is the first digit a 1?
	JB	WRITE_ONE		;No, write space already in DL
	MOV	DL,'1'			;Yes, then place '1' into DL for output
WRITE_ONE:
	CALL	WRITE_CHAR		;Write either a space or a '1'
	MOV	DL,BL			;Copy lower byte into DL for hex output
	CALL	WRITE_HEX		;Display the lower byte of offset

	MOV	DL,' '			;Write separator
	CALL	WRITE_CHAR
	MOV	DL,VERTICAL_BAR		;Draw left side of box
	CALL	WRITE_CHAR
	MOV	DL,' '			;Indent by one space from border
	CALL	WRITE_CHAR
					;Now write out 16 bytes
	MOV	CX,16			;Dump 16 bytes
	PUSH	BX			;Save the offset for ASCII_LOOP
HEX_LOOP:
	MOV	DL,SECTOR[BX]		;Get one byte
	CALL	WRITE_HEX		;Dump this byte in hex
	MOV	DL,' '			;Write a space between numbers
	CALL	WRITE_CHAR
	INC	BX			;Move to the next byte
	LOOP	HEX_LOOP		;Write 16 bytes of data

	MOV	DL,VERTICAL_BAR		;Write separator
	CALL	WRITE_CHAR
	MOV	DL,' '			;Add another space before characters
	CALL	WRITE_CHAR

	MOV	CX,16			;Now write 16 bytes of characters
	POP	BX			;Get back offset into SECTOR
ASCII_LOOP:
	MOV	DL,SECTOR[BX]		;Get one byte
	CALL	WRITE_CHAR		;Display this as a character
	INC	BX			;Move to the next byte
	LOOP	ASCII_LOOP		;Display a total of 16 characters

	MOV	DL,' '			;Write a space before the box border
	CALL	WRITE_CHAR
	MOV	DL,VERTICAL_BAR		;Write the box border
	CALL	WRITE_CHAR

	POP	DX
	POP	CX
	POP	BX
	RET
DISP_LINE	ENDP


	PUBLIC	WRITE_PROMPT_LINE
	EXTRN	CLEAR_TO_END_OF_LINE:PROC, WRITE_STRING:PROC
	EXTRN	GOTO_XY:PROC
.DATA
	EXTRN	PROMPT_LINE_NO:BYTE
.CODE
;-----------------------------------------------------------------------;
; This procedure writes the prompt line to the screen and clears the	;
; end of the line.							;
;									;
; On entry:	DS:DX	Address of the prompt-line message		;
;									;
; Uses:		WRITE_STRING, CLEAR_TO_END_OF_LINE, GOTO_XY		;
; Reads:	PROMPT_LINE_NO						;
;-----------------------------------------------------------------------;
WRITE_PROMPT_LINE	PROC
	PUSH	DX
	XOR	DL,DL			;Write the prompt line and
	MOV	DH,PROMPT_LINE_NO	; move the cursor there
	CALL	GOTO_XY
	POP	DX
	CALL	WRITE_STRING
	CALL	CLEAR_TO_END_OF_LINE
	RET
WRITE_PROMPT_LINE	ENDP


	PUBLIC	WRITE_EDITOR_PROMPT
.DATA
	EXTRN	EDITOR_PROMPT:BYTE
.CODE
;-----------------------------------------------------------------------;
; This procedure writes the editor prompt line.  We've defined it as	;
; a procedure since we need to switch to the Edit prompt in so many	;
; places.								;
;									;
; Uses:		WRITE_PROMPT_LINE					;
; Reads:	EDITOR_PROMPT						;
;-----------------------------------------------------------------------;
WRITE_EDITOR_PROMPT	PROC
	PUSH	DX
	LEA	DX,EDITOR_PROMPT
	CALL	WRITE_PROMPT_LINE
	POP	DX
	RET
WRITE_EDITOR_PROMPT	ENDP


	PUBLIC	WRITE_FUNCTION_KEYS
.DATA
	EXTRN	FUNCTION_KEY_LINE_NO:BYTE
	EXTRN	FUNCTION_KEY_LINE:BYTE
.CODE
	EXTRN	GOTO_XY:PROC, CURSOR_RIGHT:PROC
	EXTRN	WRITE_ATTRIBUTE_N_TIMES:PROC
;-----------------------------------------------------------------------;
; This procedure writes the function-key line in inverse video, with	;
; the key numbers in normal video.					;
;									;
; Uses:		GOTO_XY, WRITE_STRING, WRITE_ATTRIBUTE_N_TIMES		;
;		CURSOR_RIGHT						;
; Reads:	FUNCTION_KEY_LINE					;
;-----------------------------------------------------------------------;
WRITE_FUNCTION_KEYS	PROC
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	XOR	DL,DL			;Start a left of screen
	MOV	DH,FUNCTION_KEY_LINE_NO	;And the bottom
	CALL	GOTO_XY
	PUSH	DX			;Save start of line
	LEA	DX,FUNCTION_KEY_LINE
	CALL	WRITE_STRING
	POP	DX			;Restore start of line
	CALL	GOTO_XY			;Return to the start of this line
	MOV	AX,9			;Use as a counter
	MOV	DL,70H			;Attribute for inverse video
	MOV	CX,6			;Write 6 characters in inverse
FUNCTION_KEY_LOOP:
	CALL	CURSOR_RIGHT		;Skip over the number
	CALL	WRITE_ATTRIBUTE_N_TIMES	;Write inverse video for 6 characters
	CALL	CURSOR_RIGHT		;Skip gap
	DEC	AX			;Done yet?
	JNZ	FUNCTION_KEY_LOOP	;No, invert another word
	CALL	CURSOR_RIGHT		;Skip the last gap
	CALL	WRITE_ATTRIBUTE_N_TIMES	;Invert the 10th word
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	RET
WRITE_FUNCTION_KEYS	ENDP

	
	END
