
TITLE	DISPLAY
;  by Douglas Clark and William C. Parke (c) Copyright 1987
;
; Quick display of a page of a file on screen with special attributes
;
PUBLIC	START,BEGIN

CODE	SEGMENT
	ASSUME	CS:CODE,DS:CODE
	ORG	100H
;
CR	EQU	0DH
LF	EQU	0AH
;
START:	JMP	BEGIN
;
PAG_MAR	DB	'^'		; page marker
ATR_SYM	DB	'\'		; attribute symbol with start/stop codes

	DB	14 DUP(0)
	DB	1AH
FILNAM	DB	80 DUP(0)
PAGIDF	DB	0
	DB	0
PAGIDS	DW	0
PAGID	DB	32 DUP(0)
FHAN	DW	0
PAG_START	DW	0
PAG_SIZ		DW	0
VID_SEG	DW	0B000H			; mono addr for	direct video
PGPTR	DW	0
PGADR	DB	256 DUP(0)

HELP:	AND	AL,AL			; any error messages?
	JZ	HELP1
	XOR	AH,AH
	PUSH	AX
	DEC	AL
	SHL	AX,1
	MOV	BX,AX
	MOV	DX,WORD	PTR ERR_TBL[BX]
	MOV	AH,9H
	INT	21H
	POP	AX
	MOV	AH,4CH
	INT	21H			; exit

HELP1:	MOV	DX,OFFSET DHELP
	MOV	AH,9
	INT	21H
	MOV	AX,4C00H
	INT	21H			; EXIT clean

BEGIN:	CALL	COMMAND_LN		; get screen file name and page	id
	JC	HELP
	CALL	OPENF			; open screen file
	JC	HELP
	CALL	VID_MEM			; get video memory address
	CALL	READF
	JC	HELP
	MOV	SI,OFFSET PAGID
	MOV	DI,OFFSET FILBUF
	MOV	PAG_START,DI		; default begin	address
	MOV	CX,WORD	PTR FILBUFL
	MOV	PAG_SIZ,CX		; default size
	TEST	BYTE PTR PAGIDF,1	; test if page id is present
	JZ	VID5			; show whole file
	CALL	STRSEARCH		; look for page	id
	JC	HELP
	MOV	PAG_START,DX		; save addr. of	hit from search
	MOV	AX,DI
	SUB	AX,DX			; new size
	JC	HELP1
	MOV	PAG_SIZ,AX		; save new size
VID5:	MOV	SI,PAG_START		; SI->filbuf (or page therein)
	MOV	AX,SI
	MOV	DI,OFFSET PGADR
	STOSW
	XOR	AX,AX
	MOV	CX,126
	REP	STOSW			; zero beyond first addr
	MOV	WORD PTR PGPTR,AX	; zero the initial page ptr
	MOV	AX,VID_SEG
	MOV	ES,AX
VIDR:	MOV	BX,PGPTR		; current page index into pgadr
	MOV	SI,WORD PTR PGADR[BX]	; get address of page
	AND	SI,SI
	JNZ	VIDRN
	SUB	BX,2
	MOV	PGPTR,BX
	MOV	SI,WORD PTR PGADR[BX]
VIDRN:	CALL	CLRSCN
	MOV	BX,DI			; save di
	MOV	DX,23			; maximum lines
VID7:	LODSB
VID7C:	CMP	AL,LF			; skip Line Feeds
	JZ	VID7
	CMP	AL,CR			; chk Carr.Ret.
	JNZ	VID8			;  no
	MOV	DI,BX			; yes
	ADD	DI,(80*2)		; bump to next line on screen
	MOV	BX,DI
	DEC	DX			; 23-row count
	JNZ	VID7
	JMP	SHORT VID9
VID8:	CMP	AL,1AH			; chk e-o-f
	JZ	VID9F
	CMP	AL,'\'			; control code?
	JNZ	VIDS
	CMP	BYTE PTR [SI],'\'	; cancel?
	JZ	VIDSC
	CALL	CODES
	JMP	SHORT VID7C
VIDSC:	INC	SI
VIDS:	OR	AL,0
OCMASK	EQU	$-1
	STOSB
	MOV	AL,ATTRIB		; get attribute
	STOSB				; store attrib.
	JMP	SHORT VID7		; loop
VID9F:	XOR	SI,SI			; no more
	MOV	BX,PGPTR
	AND	BX,BX
	JZ	VID10
	TEST	BYTE PTR PAGIDF,1
	JNZ	VID10
VID9:	MOV	BX,PGPTR
	INC	BX			; next page
	INC	BX
	MOV	PGPTR,BX
	MOV	WORD PTR PGADR[BX],SI	; save ptr to next page
	JMP	SHORT VID16
VID9U:	MOV	BX,PGPTR
	SUB	BX,4
	JNC	VID9V
	XOR	BX,BX
VID9V:	MOV	PGPTR,BX
	JMP	VIDR
VID10:	MOV	AX,CS
	MOV	ES,AX			; restore ES
	MOV	AX,DI			; current screen byte count
	XOR	DX,DX
	MOV	CX,80*2			; bytes for rows
	DIV	CX			; ax= rows, dx= remainder
	SHR	DX,1			; column in dl
	MOV	DH,AL			; row in dh
	MOV	AH,02H			; locate
	MOV	BH,00H			; curr screen
	INT	10H
	MOV	AX,4C00H
	INT	21H			; terminate program

VID16:	MOV	AH,0
	INT	16H
	CMP	AX,5100H		; PgDn
	JZ	VID16R
	CMP	AX,4900H		; PgUp
	JZ	VID9U
	CMP	AX,011BH		; esc
	JZ	VID10
	CMP	AX,2E03H		; ^C
	JZ	VID10
	CMP	AX,4700H		; home
	JZ	VIDHOM
	CMP	AX,4F00H		; end
	JZ	VIDEND
	JMP	SHORT VID16
VID16R:	JMP	VIDR
VIDHOM:	MOV	WORD PTR PGPTR,0
	JMP	VIDR
VIDEND:	XOR	AX,AX
	MOV	BX,AX
	SUB	BX,2
	MOV	CX,129
VIDENS:	ADD	BX,2
	CMP	WORD PTR PGADR[BX],AX	; look for first zero address
	LOOPNZ	VIDENS
	JCXZ	VID10
	SUB	BX,2			; addr just before is 'end' one
	MOV	PGPTR,BX		; use counter for ptr
	JMP	VIDR
;
;---------------------------------------------------------------
STRSEARCH:
; Input: SI= pagid string	Output:	DX= found page position
;	 DI= file buffer		DI= end	of page	pointer
;	 CX= file buffer size
;---------------------------------------------------------------
	CLD				;forward direction
STRSR0:	CALL	SYMSEARCH		; search for pag symbol
	JNC	STRSR1
	MOV	AL,3			; error: no page symbol
	RET
STRSR1:	PUSH	CX			; save buffer length
	MOV	CX,PAGIDS
	INC	CX
	PUSH	SI
	REPZ	CMPSB			; search for page id
	POP	SI
	AND	CX,CX			; did we find it?
	POP	CX			; get back file	length remaining
	JNZ	STRSR0			; not yet
	MOV	DX,DI			; save address of first page
	CALL	SYMSEARCH
	DEC	DI
	MOV	WORD PTR [DI-1],1A1AH
	XOR	AX,AX
	RET

SYMSEARCH:
; find page break symbol in buffer
	MOV	AL,PAG_MAR
SYMSR0:	REPNZ	SCASB
	AND	CX,CX
	JNZ	SYMSR2
SYMSR1:
	STC
	RET
SYMSR2:
	DEC	CX
	JZ	SYMSR1
	SCASB
	JNZ	SYMSR0
	RET

;---------------------------------------------------------------
COMMAND_LN:
; Input: none		Output:	Command	line file name in FILNAM
;				Page code in PAGID
;---------------------------------------------------------------
	MOV	SI,80H			; get command string buffer
	LODSB				; get command string size
	AND	AL,AL			; anything there?
	JNZ	CMDLN1			; ok, there is a string
	XOR	AL,AL			; no error message
	STC
	RET
CMDLN1:	XOR	CH,CH			; zero ch
	MOV	CL,AL			; put size in cx
	INC	CX
	MOV	DI,OFFSET FILNAM	; buffer for asciz filename
CMDLN2:	LODSB				; get byte from	command	string
	CMP	AL,20H			; see if its a space
	LOOPZ	CMDLN2			; skip if so
	AND	CX,CX			; are we at end	of string?
	JNZ	CMDLNL			; not yet
CMDLNS:	XOR	AL,AL			; no error message
	STC
	RET
CMDLNL:	STOSB				; save file name byte
	LODSB				; get next byte
	CMP	AL,'/'			; switch?
	JNZ	CMDLN4			; no
	XOR	AL,AL
	STOSB
	DEC	CX
	JMP	SHORT CMDLNA		; look for page	number
CMDLNT:	XOR	AL,AL
	STOSB
	RET
CMDLN4:	CMP	AL,20H			; space?
	JZ	CMDLN5
	CMP	AL,CR
	JZ	CMDLNT
	CMP	AL,';'
	LOOPNZ	CMDLNL
	JMP	SHORT CMDLNT
CMDLN5:	XOR	AL,AL
	STOSB
	JCXZ	CMDLNT
CMDLN8:	LODSB
	CMP	AL,20H
	JZ	CMDLN9
	CMP	AL,';'
	JZ	CMDLNT
	CMP	AL,CR
	JZ	CMDLNT
	CMP	AL,'/'
	JZ	CMDLNA
CMDLN9:	LOOP	CMDLN8
	JMP	SHORT CMDLNT
CMDLNA:	CMP	CX,3
	JC	CMDLNM
CMDLNC:	LODSW				; get '=p'
	SUB	CX,2
	AND	AL,5FH
	CMP	AX,3D50H
	JZ	CMDLND
CMDLNM:	MOV	AL,1			; invalid switch
	STC
	RET
CMDLND:	MOV	DI,OFFSET PAGID
	XOR	BX,BX			; count	of pagid
CMDLNF:	LODSB
	CMP	AL,' '
	JZ	CMDLNE
	CMP	AL,CR
	JZ	CMDLNE
	CMP	AL,';'
	JZ	CMDLNE
	INC	BX
	STOSB
	LOOP	CMDLNF			; save page id
CMDLNE:	MOV	AL,PAG_MAR
	STOSB				; add ^^ to end
	INC	BX
	STOSB
	INC	BX
	MOV	PAGIDS,BX		; save size of id
	MOV	BYTE PTR PAGIDF,1	; set flag
	XOR	AX,AX
	STOSB
	RET

;---------------------------------------------------------------
OPENF:
; Input: none		Output:	 File handle in	FHAN
;---------------------------------------------------------------
	MOV	DX,OFFSET FILNAM	; DX ->	input file name
	MOV	AX,3D00H		; open for input
	INT	21H
	JNC	OPN1
	MOV	AL,2			; error	opening	file
	RET
OPN1:	MOV	FHAN,AX			; save handle
	RET

;---------------------------------------------------------------
CLRSCN:
; Input: none		Output:	 none
;---------------------------------------------------------------
	MOV	CX,0000H		; row,col
	MOV	DX,184FH		; row,col
	MOV	AX,0600H		; CLS clear screen
	MOV	BH,07H			; normal
	INT	10H
	MOV	DX,1800H		; column in dl, row in dh
	MOV	AH,02H			; locate
	MOV	BH,00H			; curr screen
	INT	10H
	XOR	DI,DI			; start at top of screen
	RET

;---------------------------------------------------------------
VID_MEM:
; Input: none		Output:	 Active	video memory address in	VID_SEG
;---------------------------------------------------------------
	MOV	AX,40H			; bios data segment
	PUSH	DS
	MOV	DS,AX			; DS ->	bios data seg.
	CMP	WORD PTR DS:63H,03B4H	; If Mono...	(everex-cga=03D4 )
	POP	DS
	JZ	VIDM1
	ADD	WORD PTR VID_SEG,0800H	; adj. for CGA
VIDM1:	RET

;---------------------------------------------------------------
READF:
; Input: none		Output:	 FILBUF	filled with file of length FILBUFL
;---------------------------------------------------------------
	MOV	DX,OFFSET FILBUF	; DX ->	file buffer
	MOV	AX,3F00H		;
	MOV	BX,FHAN
	MOV	CX,0C000H		; Read 48k
	INT	21H			;
	JNC	READ11
	MOV	AL,4			; bad read
	RET
READ11:
	MOV	WORD PTR FILBUFL,AX	; save length of file
	ADD	AX,DX			; append
	DEC	AX			;   ^Z (eof)
	MOV	BX,AX			;     to the end
	MOV	WORD PTR [BX],1A1AH	;	of the data.
	MOV	BX,FHAN
	MOV	AX,3E00H		; close	handle
	INT	21H
	RET

;---------------------------------------------------------------
CODES:
; Input: SI=file buffer at /+1		Output:	set attribute of AL
;---------------------------------------------------------------
	MOV	AL,[SI]			; get /+1 char
	PUSH	CX			; save cx
	PUSH	DI			; save di
	PUSH	ES
	PUSH	DS
	POP	ES
	MOV	DI,OFFSET COD_TBL	; point to / codes
	MOV	CX,17
	REPNZ	SCASB
	POP	ES
	POP	DI
	AND	CX,CX
	MOV	AH,CL			; save 16-count in ah
	POP	CX
	JNZ	CODE1			; jmp if we found one
	RET				; return with orig. char
CODE1:	INC	SI			; point to /+2
	PUSH	BX			; save bx
	MOV	BX,16
	SUB	BL,AH
	CMP	BX,8
	JNC	CODOFF			; must be a lower case off switch
	AND	BX,BX
	JZ	CODET			; if its zero, must be A switch
	CMP	BX,6
	JNC	CODEC			; if its above 5, must be color
	MOV	AL,COD_MSK[BX]		; get mask
	CMP	BL,5
	JNC	CODAH			; a hide request
	CMP	BL,3
	JC	CODOA			; A, I, or B request
	SUB	BL,3
	JZ	CODAA			; process U request
	OR	BYTE PTR ATTRIB,AL
	MOV	AL,11111000B		; and for reverse
CODAA:	AND	BYTE PTR ATTRIB,AL
	POP	BX
	LODSB				; get /+2 char
	RET
CODOA:	OR	BYTE PTR ATTRIB,AL	; turn on attribute requested
	POP	BX
	LODSB
	RET

CODAH:	MOV	AL,BYTE PTR ATTRIB
	MOV	ATTRH,AL		; save a copy of the attr byte
	MOV	BYTE PTR ATTRIB,0
	POP	BX
	LODSB
	RET

CODOH:	MOV	AL,BYTE PTR ATTRH
	AND	AL,AL			; test if non-zero
	JNZ	CODOH1
	MOV	AL,07H			; use default attribute
CODOH1:	MOV	BYTE PTR ATTRIB,AL	; restore copy of attr byte
	POP	BX
	LODSB
	RET

CODET:	MOV	BYTE PTR OCMASK,10000000B
	POP	BX
	LODSB
	RET
CODEU:	MOV	BYTE PTR OCMASK,00000000B
	POP	BX
	LODSB
	RET

CODOFF:	SUB	BX,8			; get displacement for off switch
	JZ	CODEU			; request to turn off alter. char.
	CMP	BX,6
	JNC	CODEC			; color request
	MOV	AL,COD_MSK[BX]		; get mask
	NOT	AL			; reverse bits
	CMP	BL,5
	JNC	CODOH			; or attribute to unhide
	CMP	BL,3
	JC	CODAA			; A, I, or B request
	SUB	BL,3
	JZ	CODOA			; process U request
	AND	BYTE PTR ATTRIB,AL
	MOV	AL,00000111B		; or for reverse off
	JMP	SHORT CODOA

CODEC:	MOV	BYTE PTR SHIFT,0	; assume foreground
	SUB	BL,6			; see if C or S
	JZ	CODESS			; do foreground Char. color
	MOV	BYTE PTR SHIFT,4	; set up background S shift
CODESS:	MOV	AL,[SI]			; get /+2
	OR	AL,' '			; make lower case
	PUSH	DI
	PUSH	ES
	PUSH	DS
	POP	ES
	PUSH	CX
	MOV	DI,OFFSET COLOR_T
	MOV	CX,8
	REPNZ	SCASB
	AND	CX,CX
	MOV	AH,CL
	POP	CX
	POP	ES
	POP	DI
	JZ	CODESE
	INC	SI			; point to /+3
	MOV	BX,7
	SUB	BL,AH
	MOV	AL,COLOR_M[BX]		; get color bit mix
	MOV	AH,11111000B		; mask for foreground
	TEST	BYTE PTR SHIFT,4
	JZ	CODESU			; no shift needed for foreground
	PUSH	CX
	XOR	CX,CX
	MOV	CL,SHIFT
	SHL	AL,CL
	POP	CX
	MOV	AH,10001111B		; mask for background
CODESU:	AND	BYTE PTR ATTRIB,AH
	OR	BYTE PTR ATTRIB,AL
	POP	BX
	LODSB				; get next real character
	RET
CODESE:	DEC	SI
	POP	BX
	MOV	AL,[SI]			; restore /+1 char.
	RET
ATTRIB	DB	7			; normal attribute
ATTRH	DB	0

COD_TBL	DB	'AIBURHCS'
	DB	'aiburhcs',0
COLOR_T	DB	'bgtrvpw',0,0
COD_MSK	DB	10000000B		; alternate char. set bit or
	DB	00001000B		; intensity bit or
	DB	10000000B		; blinking bit or
	DB	11111001B		; underline bit and
	DB	01110000B		; reverse video bits and
	DB	00000000B		; hide byte and
	DB	00000111B		; foreground bits
	DB	01110000B		; background bits

COLOR_M	DB	00000001B		; blue
	DB	00000010B		; green
	DB	00000011B		; turquoise
	DB	00000100B		; red
	DB	00000101B		; violet
	DB	00000110B		; pink
	DB	00000111B		; white
SHIFT	DB	0
	DW	0

ERR_TBL	DW	ERRSW
	DW	NOFILE
	DW	NOPAGE
	DW	ERREAD

ERRSW	DB	CR,LF,'Invalid switch on command line.',CR,LF,'$'
NOFILE	DB	CR,LF,'Cannot open file.',CR,LF,'$'
NOPAGE	DB	CR,LF,'Page Not Found.',CR,LF,'$'
ERREAD	DB	CR,LF,'Error reading file.',CR,LF,'$'

MARKEND	EQU	$
DHELP	DB	CR,LF
 DB '            DISPLAY  Version 1.1',CR,LF
 DB ' ',CR,LF
 DB '          A fast file to screen displayer',CR,LF
 DB '          by Douglas Clark and W.C. Parke',CR,LF
 DB '                  (c) 1987',CR,LF           
 DB ' ',CR,LF
 DB 'Syntax: DISPLAY filename [/P=pageid]',CR,LF
 DB '      where  filename is a valid file to display,',CR,LF
 DB '             pageid   is a page identification string',CR,LF
 DB '		     embedded in the file, with a pair of',CR,LF
 DB '		     carots (^^) on prefix and suffix.',CR,LF
 DB '      Embed ''\x'' controls in text for enhanced text:',CR,LF
 DB '      Monochrome:  Start Stop    Color: Character Screen',CR,LF
 DB '       hide           \H   \h      blue       \cb    \sb',CR,LF
 DB '       underline      \U   \u      green      \cg    \sg',CR,LF
 DB '       reverse video  \R   \r      turquoise  \ct    \st',CR,LF
 DB '       blinking       \B   \b      red        \cr    \sr',CR,LF
 DB '       intense        \I   \i      violet     \cv    \sv',CR,LF
 DB '       alternate ibm-              pink       \cp    \sp',CR,LF
 DB '        character set \A   \a      white      \cw    \sw',CR,LF,'$'

FILBUFL	EQU	MARKEND		       ; length	of file
FILBUF	EQU	FILBUFL+2	       ; 1st 48k of file
;
CODE	ENDS
	END	START
