home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
WLAX
/
ZAVT11.ZIP
/
ZAVT_P.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-05-28
|
14KB
|
473 lines
page 60,132
;----- zavt_p.asm --------------------------------------------------------
; Zephyr Avatar terminal driver.
; Copyright (C) 1989-1990, Luns Tee, Toronto, ON
; Based on original code for ZANSI by Thomas Hanlin III, Alexandria VA.
; and original code for NANSI by Daniel Kegel, Pasadena CA.
;------------------------------------------------------------------------
; A state machine implementation of the mechanics of ANSI terminal control
; string parsing.
;
; Entered with a jump to f_escape when driver finds an escape, or
; to f_in_escape when the last string written to this device ended in the
; middle of an escape sequence.
;
; Exits by jumping to f_ANSI_exit when an escape sequence ends, or
; to f_control when a bad escape sequence is found, or (after saving state)
; to f_loopdone when the write ends in the middle of an escape sequence.
;
; Parameters are stored as bytes in param_buffer. If a parameter is
; omitted, it is stored as zero. Each character in a keyboard reassignment
; command counts as one parameter.
;
; When a complete escape sequence has been parsed, the address of the
; ANSI routine to call is found in ansi_fn_table.
;
; Register usage during parsing:
; DS:SI points to the incoming string.
; CX holds the length remaining in the incoming string.
; ES:DI points to the current location on the memory-mapped screen.
; DX is number of characters remaining on the current screen line.
; BX points to the current paramter byte being assembled from the incoming
; string. (Stored in cur_parm_ptr between device driver calls, if needed.)
;
; The registers are set as follows before calling the ANSI subroutine:
; AX = max(1, value of first parameter)
; CX = number of paramters
; SI = offset of second parameter from CS
; DS = CS
; ES:DI points to the current location on the memory-mapped screen.
; DX is number of characters remaining on the current screen line.
; The subroutine is free to trash AX, BX, CX, SI, and DS.
; It must preserve ES, and can alter DX and DI if it wants to move the
; cursor.
;
; Revision History:
;------------------------------------------------------------------------
; Luns Tee, Toronto Ontario
;
; 16 Nov 1989; rewrote parse routines so a colon not preceeded by a number
; acts as predicted. Spaghetti mostly gone.
;
; 27 Dec 1989; Added support for AVATAR/0 except for ^Y RLE (being planned)
; and added switches in ZANSI_D for AVATAR, direct scroll
; override (for back-scroll users), and left margin wrap
;
; 4 Feb 1990; Finished off RLE support, commented all code not in ZANSI12
; and renamed to ZAVT.
;------------------------------------------------------------------------
include zavt_d.asm
; From zavt.asm
extrn f_control:near ; exit: abort bad ANSI cmd
extrn f_looploop:near ; exit: good cmd done
extrn f_loopdone:near ; exit: ran out of chars. State saved.
extrn escvector:word ; saved state: where to jump
extrn cur_parm_ptr:word ; saved state: where to put next param
extrn string_term:byte ; saved state: what ends string
extrn cur_x:byte, max_x:byte ; 0 <= cur_x < max_x
extrn cur_attrib:byte ; current color/attribute
extrn string_attrib:word ; for quick attribute access
if avatar
extrn f_nctl:near
extrn f_loop_nocheck:near
extrn gmode_flag:byte
extrn putchar:near
endif
; from zavt_f.asm
extrn ansi_fn_table:word ; ANSI subroutine table
; Used in zavt.asm
public f_escape ; entry: found an escape
public f_in_escape ; entry: restore state, keep parsing
if avatar
public avt_cls
public f_avatar
public dle
public rle
endif
; from zavt_p.asm
extrn param_buffer:abs
if xlate
extrn param_end:word
else
extrn param_end:abs
endif
code segment byte public 'CODE'
assume cs:code
; More saved state
if avatar
repeater db ?
count db ?
endif
;----- next_is -------------------------------------------------------
; Next_is is used to advance to the next state. If there are characters
; left in the input string, we jump immediately to the new state;
; otherwise, we shut down the recognizer, and wait for the next call
; to the device driver.
next_is macro statename
loop statename
mov ax, offset statename
jmp sleep
endm
if avatar
;----- avt_cls -------------------------------------------------------
; Calls the ANSI EID when a ^L is encountered
avt_cls:
mov cs:cur_attrib,3
mov bx,param_buffer
mov byte ptr cs:[bx],2 ; stick a 2J (CLS)
mov al,'J' ; in the parameter buffer
jmp call_cmd ; and call EID
;----- dle ----------------------------------------------------------
; last character was our DLE flag - make sure next character
; isn't interpreted as a control character
dle: next_is get_dle
get_dle:
lodsb ; get character to pass
and al,7fh ; strip high bit
mov cs:escvector, 0 ; No longer parsing
jmp f_nctl ; go back and print it
;----- rle -----------------------------------------------------------
; first character to follow is to be repeated by count in second byte
rle: next_is get_repeater
get_repeater:
lodsb ; get character to repeat
mov cs:repeater,al ; store it
next_is get_count
get_count:
lodsb ; get number of times to repeat
mov cs:escvector, 0 ; no more parsing required
push cx ; save cx
mov cl,al ; put count into cx
mov ch,dh ; zero high byte
mov al,cs:repeater ; and put character into al
; ah is still current attribute.
cmp cs:gmode_flag,dh
jnz f_tp_lp
sub dx, cx ; update chars-to-eol, maybe set z
jnc nochop ; in case of wrap, chop the count
add cx,dx ; so we don't get a neg DX
xor dx,dx
nochop: rep stosw
pop cx ; restore cx
jmp f_loop_nocheck ; Let main loop decrement cx.
;--------------- graphics mode support -----------------------
f_tp_lp: ; graphics mode- call putc to put the char
call putchar
dec dx ; go to next cursor position
loopnz f_tp_lp
pop cx
jmp f_loop_nocheck
;----- f_avatar ------------------------------------------------------
; Last character was avatar ESC. Get subcode
f_avatar:
next_is f_in_avatar
avt_tabl label word
dw get_attr,set_blink,curs,curs,curs,curs,EIL,HVP
get_attr:
next_is set_attr
set_attr:
lodsb ; get byte to set attribute to
cmp al,10h ; ^P: DLE?
jnz not_dle_attrib ; if not, process it
next_is get_real_attr
get_real_attr:
lodsb ; else get next character
not_dle_attrib:
and al,7fh ; strip high bit
mov ah,al ; and set attribute to it
got_attrib:
mov cs:string_attrib,ax ; stash away attribute
mov cs:escvector, 0 ; No longer parsing
jmp f_looploop
set_blink:
or ah,80h ; set the high bit
jmp got_attrib ; and store it
curs: sub al,2 ; a little bitshifting
mov [si-1],al ; to get the proper
shr al,1 ; ANSI code out of
xor al,[si-1] ; the Avatar
add al,"A"
cmd_zero:
mov bx,param_buffer ; put it in the command buffer
mov byte ptr cs:[bx],dh ; make the first parameter zero
jmp call_cmd ; and call the command
EIL: mov al,"K" ; call ANSI - 0K
jmp cmd_zero
HVP: mov bx,param_buffer
next_is get_row
get_row:
lodsb ; get the row and put it in
mov cs:[bx],al ; the parameter buffer
inc bx ; increment the buffer pointer
next_is get_col
get_col:
lodsb ; put away the column as well
mov cs:[bx],al
mov al,"H" ; and call ANSI HVP
jmp call_cmd
;----- f_in_avatar ---------------------------------------------------
; Get avatar subcode, do what's appropriate
f_in_avatar:
lodsb ; get subcode
dec ax ; make the table pointer zero based
cmp al,7 ; check for invalid code
jbe valid_avt_code
inc ax ; if so, restore it
jmp short fbr_syntax_error_gate ; and leave
valid_avt_code:
mov bh,dh ; put pointer
mov bl,al ; into bx
shl bx,1 ; byte address
jmp word ptr cs:avt_tabl[bx]
endif
;----- sleep --------------------------------------------------------
; Remember bx and next state, then jump to device driver exit routine.
; Device driver will re-enter at f_in_escape upon next invocation
; because escvector is nonzero; parsing will then be resumed.
sleep: mov cs:cur_parm_ptr, bx
mov cs:escvector, ax
jmp f_loopdone
;----- f_in_escape ---------------------------------------------------
; Main loop noticed that escvector was not zero.
; Recall value of BX saved when sleep was jumped to, and jump into parser.
f_in_escape:
mov bx, cs:cur_parm_ptr
jmp word ptr cs:escvector
;----- f_escape ------------------------------------------------------
; We found an escape. Next character should be a left bracket.
f_escape:
next_is f_bracket
;----- f_bracket -----------------------------------------------------
; Last char was an escape. This one should be a [; if not, print it.
; Next char should begin a parameter string.
f_bracket:
lodsb
cmp al, '['
jnz fbr_syntax_error_gate
; Set up for getting a parameter string.
mov bx, param_buffer-1
mov cs:[bx+1],dh
next_is f_get_args
;----- f_get_args ---------------------------------------------------
; Last char was a [. If the current char is a '=' or a '?', eat it.
; In any case, proceed to f_get_param.
; This is only here to strip off the strange chars that follow [ in
; the SET/RESET MODE escape sequence.
f_get_args:
lodsb
cmp al, '='
jz fga_ignore
cmp al, '?'
jz fga_ignore
dec si ; let f_get_param fetch al again
jmp short f_get_param
fga_ignore:
next_is f_get_param
;----- f_get_string -------------------------------------
; Last character was a quote or a string element.
; Get characters until ending quote found.
f_get_string:
lodsb
cmp al, cs:string_term
jnz stillstring
next_is f_eat_semi ; Ending quote was found.
stillstring:
cmp bx, param_end
adc bx, 0 ; if bx<param_end bx++;
mov byte ptr cs:[bx], al
next_is f_get_string
;----- f_eat_semi -------------------------------------
; Last character was an ending quote.
; If this char is a semi, eat it; else unget it.
; Next state is always f_get_param.
f_eat_semi:
lodsb
cmp al, ';'
jz fes_eaten
inc cx
dec si
fes_eaten:
next_is f_get_param
fbr_syntax_error_gate: ; jumped to from inside f_bracket
jmp short syntax_error
;----- f_get_param ---------------------------------------------------
; Last char was one of the four characters "[?=;".
; We are getting the first digit of a parameter, a quoted string,
; a ;, or a command.
f_get_param:
lodsb
cmp al, '0'
jb fgp_may_quote
cmp al, '9'
ja fgp_may_semi
; It's the first digit. Initialize current parameter with it.
sub al,'0'
cmp bx, param_end
adc bx, 0 ; if bx<param_end bx++;
mov byte ptr cs:[bx], al
next_is f_in_num
fgp_may_quote:
cmp al, '"'
jz fgp_isquote
cmp al, "'"
jnz syntax_error
fgp_isquote:
mov cs:string_term, al ; save it for end of string
next_is f_get_string ; and read string into param_buffer
fgp_may_semi:
cmp al, ';'
jnz call_cmd ; jump to code shared with f_in_num
cmp bx, param_end
adc bx, 0 ; if bx<param_end bx++;
mov cs:[bx],dh
next_is f_get_param
;------ f_in_num -------------------------------------
; Last character was a digit.
; Looking for more digits, a semicolon, or a command character.
f_in_num:
lodsb
cmp al, '0'
jb syntax_error
cmp al, '9'
ja fgp_semi_or_cmd
; It's another digit. Add into current parameter.
sub al,'0'
push dx
mov dl,byte ptr cs:[bx]
shl dx,1 ;mul dx,10
add ax,dx ;add ax,dx
if is_8088
shl dx,1
shl dx,1
else
shl dx,2
endif
add ax,dx
mov byte ptr cs:[bx],al
pop dx
next_is f_in_num
fgp_semi_or_cmd:
cmp al, ';'
jnz call_cmd
next_is f_get_param
;----- syntax_error ---------------------------------------
; A character was rejected by the state machine. Exit to
; main loop, and print offending character. Let main loop
; decrement CX (length of input string).
syntax_error:
mov cs:escvector, 0
mov ah, cs:cur_attrib
jmp f_control ; exit, print offending char
;----- call_cmd ---------------------------------------------
; Character in AL isn't a paramater or delimiter, so
; either call the appropriate command or abort with
; a syntax error.
call_cmd:
; It must be a command letter.
cmp al, '@'
jb syntax_error
cmp al, 'Z'
jbe fgp_is_cmd
cmp al, 'z'
ja syntax_error
cmp al, 'a'
jb syntax_error
; It's a lower-case command letter.
; Remove hole between Z and a to save space in table.
sub al, 'a'-'['
fgp_is_cmd:
; It's a command letter. Save registers, convert letter
; into address of routine, set up new register usage, call routine.
push si ; These three registers hold info
push cx ; having to do with the input string,
push ds ; which has no interest at all to the
; control routine.
push cs
pop ds ; ds is now cs
cbw ; zero ah
mov cx, bx
mov si, param_buffer ; si is now pointer to parameters
sub cx, si ; cx is now # of parameters
inc cx
mov bh,ah
shl ax,1
; ax is now pointer to command routine address in table
xchg bx,ax ; save pointer to routine in bx
; Calculate cur_x from DX.
mov al, max_x
sub al, dl
mov cur_x, al
; Get first parameter into AX; if defaulted, set it to 1.
lodsb
cmp al,1 ; if ax<1 ax++;
adc al,ah
; Finally, call the command subroutine.
call word ptr (ansi_fn_table-2*'@')[bx]
pop ds
pop cx
pop si
mov ax, cs:string_attrib ; Prepare for STOSW.
mov cs:escvector, 0 ; No longer parsing escape sequence.
; Re-enter at bottom of main loop.
jmp f_looploop
code ends
end