		page	60,132
title		SCREEN.ASM--Sends escape seq's to ANSI.SYS driver.

;	Table entry macro.
;****************************************

entry		macro	color,nn
		local	top
top		equ	this byte		;; mark the top
		db	'&color'		;; table entry:  color string
		org	offset (top + 10)	;; force table entry to 10th byte
		db	27,'[&nn&m$'		
		org	offset (top + 16)	;; force table entry to be 16 bytes long
		endm


;	Program prefix structure.
;****************************************

prefix		struc			; layout of prefix
		db	80h dup (?)	; don't care about 1st 80h bytes
p_count		db	?		; one byte length count of parms
parms		db	07fh dup (?)	; parameter buffer
prefix		ends

		page

;	Mainline.
;****************************************

screen		segment para public 'code'
		org	100h		; .com file
scr		proc	far		; entered by a long jmp
		assume	cs:screen	; All of the 
		assume	ds:screen	; 	segment registers
		assume	es:screen	;	will point to the
		assume	ss:screen	;	prefix upon entry.
					; SP points to 0fffe (end of segment).

;	Convert parms to lower case.
;****************************************

		xor	cx,cx		; clear the count reg.
		mov	cl,ds:p_count	; cx now=to length of parms.
		cmp	cx,0		; if cx=0, there were no parms
		jne	uc_to_lc	; So, if .ne. 0, continue.
		jmp	help		; Else, assume help request.
uc_to_lc:	mov	si,cx		; UC-to_LC loop.
		mov	al,ds:parms[si]	; last char in the parms string into al.
		cmp	al,'A'		; Is it below an UC 'A'?
		jb	uc_lc_loop	; Yes--leave it alone, loop for next char.
		cmp	al,'Z'		; Is it above an UC 'Z'?
		ja	uc_lc_loop	; Yes--loop for next character.
		add	al,'a'-'A'	; Convert Uc to LC.
		mov	ds:parms[si],al	; Store it back in parms.
uc_lc_loop:	loop	uc_to_lc	; loop control.


;	Parse for operands.
;****************************************

		cld			; left to right.
		lea	di,ds:parms	; di=offset of parameter string
		mov	al,020h		; blanks (spaces) are delimeters
		xor	cx,cx		; clear count register (for safety's sake)
		mov	cl,ds:p_count	; count reg. now=length of parameter string.
	repe	scasb			; bypass leading blanks, usually just 1.
		jz	help		; if all blanks, assume help request
adjust:		dec	di		; back up so di=offset of 1st non-blank.
		inc	cx		; correct count of bytes remaining in parms.
		page


	;	Register usage.
	;	***************
	; cx=count length of parms
	; di=offset of parms
	; si=offset of table start
	; bx=original count before scan starts
	; bp=di at start (i.e., saves begining offset of operands)
	; ax=count after scan (i.e., saves remaining count of the rest of the parms)
	; dx=offset of next operand after the scan (i.e., saves our place)

table_search:	lea	si,table	; si=offset of table for comparisons
		mov	bx,cx		; save original count
		mov	bp,di		; save offset of operand start
	repne	scasb			; find the next blank (delimiter)
		mov	dx,di		; save offset of next operand
		jcxz	past		; if last operand, bx already=length
		push	cx		; save remaining count
		inc	cx		; adjust cx for length calc.
		sub	bx,cx		; calc. length; bx now=length of operand
past:		mov	cx,bx		; count in cx for cmps
		mov	di,bp		; point at start of operand
		push	si		; save current place in the table
	repe	cmpsb			; compare operand to table entry
		je	found		; A hit?  Yes--go process esc string.
		pop	ax		; No--get back offset of table argument.
		add	ax,16		; Bump up to next table entry.
		mov	si,ax		; Put it in the index register.
		mov	ax,0ffffh	; End of table mark in ax.
		cmp	ax,[ds:si]	; Are we at the end of the table?
		je	error		; Yes--bad operand.  Go die.
		jmp	past		; No--go check next table entry.
found:		mov	di,dx		; next operand offset in di (for later)
		pop	dx		; offset of table entry in dx
		add	dx,10		; point at escape string.
		mov	ah,9		; DOS screen function.
		int	021h		; Issue DOS call.  (will be filtered by ANSI.SYS)
		pop	cx		; Retrieve the remaining parms string count.
		cmp	cx,0		; Are we at the end of the parms string?
		jz	quit		; If so--all done.
		mov	al,020h		; If not--set up for next scan.
		cmp	al,[ds:di]	; Is next byte is blank?
		jne	table_search	; No--all is well, loop back to table search.
	repe	scasb			; Otherwise--bypass all imbedded blanks.
		jz	quit		; If all trailing blanks, quit.
		jmp	adjust		; Loop back to adjust regs. and table search.
		page
;	Help routine.
;****************************************

help:		mov	dx,offset clear_screen	; point at clear screen esc sequece
		mov	ah,9		; DOS screen function.
		int	021h		; go clear the screen
		mov	dx,offset help_msg 	; point at help messages.
		mov	ah,9		; DOS screen function.
		int	021h		; Issue DOS call.
		int	020h		; And die.....

;	Error Routine
;****************************************

Comment *
	The error routine is entered whenever an operand is not found
	in the table.  If the operand is "help" the help screen is
	printed.  Otherwise, an error message is issued and the program
	terminates.
	
	Upon entry:  bx=length of the bad parameter
		     bp=offset of the bad parameter in the buffer
	*	
error:		mov	cx,bx		; get length of bad parm.
		mov	di,bp		; and get it's start offset
		mov	si,offset help_string	; point at "help" for comparison
	repe	cmpsb			; see if bad parm was "help"
		je	help		; if it was, go print the help screen.
		mov	dx,offset cr_lf_$	; if not, do the error stuff.
		mov	ah,09h		; first, space down the screen
		int	021h		; with a cr,lf
		add	bx,bp		; calc. the end of the bad operand
		mov	byte ptr [ds:bx],'$'	; mark the end of it for screen function

		mov	dx,bp		; point at the bad parm
		int	021h		; display it on the screen...
		mov	dx,offset error_message	; set up the rest of the error message
		int	021h		; and display it too.
quit:		int	020h		; standard exit point of the program. 

cr		equ	00dh		; ascii carriage return
lf		equ	00ah		; ascii line feed
help_string	db	'help'		; "help" string for checking potential help req's
cr_lf_$		db	cr,lf,'$'	; cr, lf, $...could you guess?
error_message	db	' is an invalid operand.',cr,lf
		db	'Issue "A>screen" with no operands for help.',cr,lf,lf
		db	'$'		; end of string marker.

clear_screen	db	27,'[2J','$'	; escape sequence to clear screen
help_msg	db	'ANSI.SYS and CONFIG.SYS (containing the line DEVICE=ANSI.SYS)',cr,lf
		db	'must be accessable when the PC is booted.  Type "screen" and then your',cr,lf
		db	'choices of foreground, intensity, or background color(s) from the',cr,lf
		db	'following list of parameters:',cr,lf
		db	'     black    bblack    red    bred    green    bgreen',cr,lf
		db	'     amber    bamber    yellow byellow blue     bblue',cr,lf
		db	'     magenta  bmagenta  cyan   bcyan   white    bwhite',cr,lf
		db	'     clear    bright    underscore     reverse',cr,lf,lf
		db	'For example:',cr,lf,lf
		db	'     A>screen bright yellow bred',cr,lf,lf
		db	'This would result in a yellow foreground, red background.',cr,lf,lf
		db	'Note:  Yellow is really amber.  To get real yellow use bright yellow.  ',cr,lf
		db	'You need only enter enough of an  operand for the program to get ',cr,lf
		db	'a valid comparison.  For example, "bg" is good enough for green background,',cr,lf
		db	'but you need at least "bblu" for blue background.  Any less and the',cr,lf
		db	'program will get it confused with "bbla" (black background).',cr,lf,lf
		db	'Note:  "underscore" only works with IBM monochrome monitors.',cr,lf
		db	'	 Colors only work with color monitors.',cr,lf
		db	'$'		; end of string marker 


		




		page
		even			; force even alignment
no_entries	equ	24		; number of table entries
entry_len	equ	16		; length of table entry
table		equ	this byte	; Color table
		entry	amber,33	; amber foreground
		entry	bamber,43	; amber background
		entry	bblack,40	; black background
		entry	bblue,44	; blue background
		entry	bcyan,46	; cyan background
		entry	bgreen,42	; green background
		entry	black,30	; black foreground
		entry	blue,34		; blue foreground
		entry	blink,5		; blinking everything
		entry	bmagenta,45	; magenta background
		entry	bold,1		; bold everything
		entry	bred,41		; red background
		entry	bright,1	; bright everything (same as bold)
		entry	bwhite,47	; white background
		entry	byellow,43	; yellow background
		entry	clear,0		; clear all settings
		entry	cyan,36		; cyan foreground
		entry	green,32	; green foreground
		entry	magenta,35	; magenta foreground
		entry	red,31		; red foreground
		entry	reverse,7	; reverse video
		entry	underscore,4	; underline everything
		entry	white,37	; white foreground
		entry	yellow,33	; yellow foreground (same as amber)
		dw	0ffffh		; end of table mark

scr		endp			; proc ends
screen		ends			; segment ends
		end	scr		; code ends	
