home *** CD-ROM | disk | FTP | other *** search
- 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