home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / WLAX / ZAVT11.ZIP / ZAVT_P.ASM < prev    next >
Assembly Source File  |  1990-05-28  |  14KB  |  473 lines

  1. page    60,132
  2. ;----- zavt_p.asm --------------------------------------------------------
  3. ; Zephyr Avatar terminal driver.
  4. ;    Copyright (C) 1989-1990, Luns Tee, Toronto, ON
  5. ;    Based on original code for ZANSI by Thomas Hanlin III, Alexandria VA.
  6. ;    and original code for NANSI by Daniel Kegel, Pasadena CA.
  7. ;------------------------------------------------------------------------
  8. ; A state machine implementation of the mechanics of ANSI terminal control
  9. ; string parsing.
  10. ;
  11. ; Entered with a jump to f_escape when driver finds an escape, or
  12. ; to f_in_escape when the last string written to this device ended in the
  13. ; middle of an escape sequence.
  14. ;
  15. ; Exits by jumping to f_ANSI_exit when an escape sequence ends, or
  16. ; to f_control when a bad escape sequence is found, or (after saving state)
  17. ; to f_loopdone when the write ends in the middle of an escape sequence.
  18. ;
  19. ; Parameters are stored as bytes in param_buffer.  If a parameter is
  20. ; omitted, it is stored as zero.  Each character in a keyboard reassignment
  21. ; command counts as one parameter.
  22. ;
  23. ; When a complete escape sequence has been parsed, the address of the
  24. ; ANSI routine to call is found in ansi_fn_table.
  25. ;
  26. ; Register usage during parsing:
  27. ;  DS:SI points to the incoming string.
  28. ;  CX holds the length remaining in the incoming string.
  29. ;  ES:DI points to the current location on the memory-mapped screen.
  30. ;  DX is number of characters remaining on the current screen line.
  31. ;  BX points to the current paramter byte being assembled from the incoming
  32. ;  string.  (Stored in cur_parm_ptr between device driver calls, if needed.)
  33. ;
  34. ; The registers are set as follows before calling the ANSI subroutine:
  35. ;  AX = max(1, value of first parameter)
  36. ;  CX = number of paramters
  37. ;  SI = offset of second parameter from CS
  38. ;  DS = CS
  39. ;  ES:DI points to the current location on the memory-mapped screen.
  40. ;  DX is number of characters remaining on the current screen line.
  41. ; The subroutine is free to trash AX, BX, CX, SI, and DS.
  42. ; It must preserve ES, and can alter DX and DI if it wants to move the
  43. ; cursor.
  44. ;
  45. ; Revision History:
  46. ;------------------------------------------------------------------------
  47. ; Luns Tee, Toronto Ontario
  48. ;
  49. ; 16 Nov 1989;    rewrote parse routines so a colon not preceeded by a number
  50. ;        acts as predicted. Spaghetti mostly gone.
  51. ;
  52. ;  27 Dec 1989;    Added support for AVATAR/0 except for ^Y RLE (being planned)
  53. ;        and added switches in ZANSI_D for AVATAR, direct scroll
  54. ;        override (for back-scroll users), and left margin wrap
  55. ;
  56. ;  4 Feb 1990;    Finished off RLE support, commented all code not in ZANSI12
  57. ;        and renamed to ZAVT.
  58. ;------------------------------------------------------------------------
  59.     include    zavt_d.asm
  60.  
  61.     ; From zavt.asm
  62.     extrn    f_control:near         ; exit: abort bad ANSI cmd
  63.     extrn    f_looploop:near        ; exit: good cmd done
  64.     extrn    f_loopdone:near     ; exit: ran out of chars. State saved.
  65.     extrn    escvector:word        ; saved state: where to jump
  66.     extrn    cur_parm_ptr:word    ; saved state: where to put next param
  67.     extrn    string_term:byte    ; saved state: what ends string
  68.     extrn    cur_x:byte, max_x:byte    ; 0 <= cur_x < max_x
  69.     extrn    cur_attrib:byte     ; current color/attribute
  70.     extrn    string_attrib:word    ; for quick attribute access
  71.     if    avatar
  72.     extrn    f_nctl:near
  73.     extrn    f_loop_nocheck:near
  74.     extrn    gmode_flag:byte
  75.     extrn    putchar:near
  76.     endif
  77.  
  78.     ; from zavt_f.asm
  79.     extrn    ansi_fn_table:word    ; ANSI subroutine table
  80.  
  81.     ; Used in zavt.asm
  82.     public    f_escape        ; entry: found an escape
  83.     public    f_in_escape        ; entry: restore state, keep parsing
  84.     if    avatar
  85.     public    avt_cls
  86.     public    f_avatar
  87.     public    dle
  88.     public    rle
  89.     endif
  90.  
  91.     ; from zavt_p.asm
  92.     extrn    param_buffer:abs
  93.     if    xlate
  94.     extrn    param_end:word
  95.     else
  96.     extrn    param_end:abs
  97.     endif
  98.  
  99.  
  100. code    segment byte public 'CODE'
  101.     assume    cs:code
  102.  
  103. ; More saved state
  104.     if    avatar
  105. repeater    db    ?
  106. count        db    ?
  107.     endif
  108.  
  109. ;----- next_is -------------------------------------------------------
  110. ; Next_is is used to advance to the next state.  If there are characters
  111. ; left in the input string, we jump immediately to the new state;
  112. ; otherwise, we shut down the recognizer, and wait for the next call
  113. ; to the device driver.
  114. next_is macro    statename
  115.     loop    statename
  116.     mov    ax, offset statename
  117.     jmp    sleep
  118.     endm
  119.  
  120.     if    avatar
  121. ;----- avt_cls -------------------------------------------------------
  122. ; Calls the ANSI EID when a ^L is encountered
  123. avt_cls:
  124.     mov    cs:cur_attrib,3
  125.     mov    bx,param_buffer
  126.     mov    byte ptr cs:[bx],2    ; stick a 2J (CLS)
  127.     mov    al,'J'            ; in the parameter buffer
  128.     jmp    call_cmd        ; and call EID
  129.  
  130. ;----- dle ----------------------------------------------------------
  131. ; last character was our DLE flag - make sure next character
  132. ; isn't interpreted as a control character
  133. dle:    next_is    get_dle
  134. get_dle:
  135.     lodsb                ; get character to pass
  136.     and    al,7fh            ; strip high bit
  137.     mov    cs:escvector, 0     ; No longer parsing
  138.     jmp    f_nctl            ; go back and print it
  139.  
  140. ;----- rle -----------------------------------------------------------
  141. ; first character to follow is to be repeated by count in second byte
  142. rle:    next_is    get_repeater
  143. get_repeater:
  144.     lodsb                ; get character to repeat
  145.     mov    cs:repeater,al        ; store it
  146.     next_is    get_count
  147. get_count:
  148.     lodsb                ; get number of times to repeat
  149.     mov    cs:escvector, 0        ; no more parsing required
  150.     push    cx            ; save cx
  151.     mov    cl,al            ; put count into cx
  152.     mov    ch,dh            ; zero high byte
  153.     mov    al,cs:repeater        ; and put character into al
  154.                     ; ah is still current attribute.
  155.  
  156.     cmp    cs:gmode_flag,dh
  157.     jnz    f_tp_lp
  158.     sub    dx, cx            ; update chars-to-eol, maybe set z
  159.     jnc    nochop            ; in case of wrap, chop the count
  160.     add    cx,dx            ; so we don't get a neg DX
  161.     xor    dx,dx
  162. nochop:    rep    stosw
  163.     pop    cx            ; restore cx
  164.     jmp    f_loop_nocheck        ; Let main loop decrement cx.
  165.  
  166. ;--------------- graphics mode support -----------------------
  167.  
  168. f_tp_lp:        ; graphics mode- call putc to put the char
  169.     call    putchar
  170.     dec    dx            ; go to next cursor position
  171.     loopnz    f_tp_lp
  172.     pop    cx
  173.     jmp    f_loop_nocheck
  174.  
  175.  
  176. ;----- f_avatar ------------------------------------------------------
  177. ; Last character was avatar ESC. Get subcode
  178. f_avatar:
  179.     next_is    f_in_avatar
  180.  
  181. avt_tabl    label    word
  182.     dw    get_attr,set_blink,curs,curs,curs,curs,EIL,HVP
  183.  
  184. get_attr:
  185.     next_is    set_attr
  186. set_attr:
  187.     lodsb            ; get byte to set attribute to
  188.     cmp    al,10h        ; ^P: DLE?
  189.     jnz    not_dle_attrib    ; if not, process it
  190.     next_is    get_real_attr
  191. get_real_attr:
  192.     lodsb            ; else get next character
  193. not_dle_attrib:
  194.     and    al,7fh        ; strip high bit
  195.     mov    ah,al        ; and set attribute to it
  196. got_attrib:
  197.     mov    cs:string_attrib,ax    ; stash away attribute
  198.     mov    cs:escvector, 0     ; No longer parsing
  199.     jmp    f_looploop
  200.  
  201. set_blink:
  202.     or    ah,80h        ; set the high bit
  203.     jmp    got_attrib    ; and store it
  204.  
  205. curs:    sub    al,2        ; a little bitshifting
  206.     mov    [si-1],al    ; to get the proper
  207.     shr    al,1        ; ANSI code out of
  208.     xor    al,[si-1]    ; the Avatar
  209.     add    al,"A"
  210.  
  211. cmd_zero:
  212.     mov    bx,param_buffer        ; put it in the command buffer
  213.     mov    byte ptr cs:[bx],dh    ; make the first parameter zero
  214.     jmp    call_cmd        ; and call the command
  215.  
  216. EIL:    mov    al,"K"        ; call ANSI - 0K
  217.     jmp    cmd_zero
  218.  
  219. HVP:    mov    bx,param_buffer
  220.     next_is    get_row
  221. get_row:
  222.     lodsb            ; get the row and put it in
  223.     mov    cs:[bx],al    ; the parameter buffer
  224.     inc    bx        ; increment the buffer pointer
  225.     next_is    get_col
  226. get_col:
  227.     lodsb            ; put away the column as well
  228.     mov    cs:[bx],al
  229.     mov    al,"H"        ; and call ANSI HVP
  230.     jmp    call_cmd
  231.  
  232. ;----- f_in_avatar ---------------------------------------------------
  233. ; Get avatar subcode, do what's appropriate
  234. f_in_avatar:
  235.     lodsb            ; get subcode
  236.     dec    ax        ; make the table pointer zero based
  237.     cmp    al,7        ; check for invalid code
  238.     jbe    valid_avt_code
  239.     inc    ax        ; if so, restore it
  240.     jmp    short fbr_syntax_error_gate    ; and leave
  241.  
  242. valid_avt_code:
  243.     mov    bh,dh        ; put pointer
  244.     mov    bl,al        ; into bx
  245.     shl    bx,1        ; byte address
  246.     jmp    word ptr cs:avt_tabl[bx]
  247.  
  248.     endif
  249.  
  250. ;----- sleep --------------------------------------------------------
  251. ; Remember bx and next state, then jump to device driver exit routine.
  252. ; Device driver will re-enter at f_in_escape upon next invocation
  253. ; because escvector is nonzero; parsing will then be resumed.
  254. sleep:    mov    cs:cur_parm_ptr, bx
  255.     mov    cs:escvector, ax
  256.     jmp    f_loopdone
  257.  
  258. ;----- f_in_escape ---------------------------------------------------
  259. ; Main loop noticed that escvector was not zero.
  260. ; Recall value of BX saved when sleep was jumped to, and jump into parser.
  261. f_in_escape:
  262.     mov    bx, cs:cur_parm_ptr
  263.     jmp    word ptr cs:escvector
  264.  
  265. ;----- f_escape ------------------------------------------------------
  266. ; We found an escape.  Next character should be a left bracket.
  267. f_escape:
  268.     next_is f_bracket
  269.  
  270. ;----- f_bracket -----------------------------------------------------
  271. ; Last char was an escape.  This one should be a [; if not, print it.
  272. ; Next char should begin a parameter string.
  273. f_bracket:
  274.     lodsb
  275.     cmp    al, '['
  276.     jnz    fbr_syntax_error_gate
  277.                     ; Set up for getting a parameter string.
  278.     mov    bx, param_buffer-1
  279.     mov    cs:[bx+1],dh
  280.     next_is f_get_args
  281.  
  282. ;----- f_get_args ---------------------------------------------------
  283. ; Last char was a [.  If the current char is a '=' or a '?', eat it.
  284. ; In any case, proceed to f_get_param.
  285. ; This is only here to strip off the strange chars that follow [ in
  286. ; the SET/RESET MODE escape sequence.
  287. f_get_args:
  288.     lodsb
  289.     cmp    al, '='
  290.     jz    fga_ignore
  291.     cmp    al, '?'
  292.     jz    fga_ignore
  293.     dec    si            ; let f_get_param fetch al again
  294.     jmp    short f_get_param
  295. fga_ignore:
  296.     next_is f_get_param
  297.  
  298. ;----- f_get_string -------------------------------------
  299. ; Last character was a quote or a string element.
  300. ; Get characters until ending quote found.
  301. f_get_string:
  302.     lodsb
  303.     cmp    al, cs:string_term
  304.     jnz    stillstring
  305.     next_is    f_eat_semi        ; Ending quote was found.
  306.  
  307. stillstring:
  308.     cmp    bx, param_end
  309.     adc    bx, 0            ; if bx<param_end bx++;
  310.     mov    byte ptr cs:[bx], al
  311.     next_is f_get_string
  312.  
  313. ;----- f_eat_semi -------------------------------------
  314. ; Last character was an ending quote.
  315. ; If this char is a semi, eat it; else unget it.
  316. ; Next state is always f_get_param.
  317. f_eat_semi:
  318.     lodsb
  319.     cmp    al, ';'
  320.     jz    fes_eaten
  321.     inc    cx
  322.     dec    si
  323. fes_eaten:
  324.     next_is f_get_param
  325.  
  326. fbr_syntax_error_gate:            ; jumped to from inside f_bracket
  327.     jmp    short syntax_error
  328.  
  329. ;----- f_get_param ---------------------------------------------------
  330. ; Last char was one of the four characters "[?=;".
  331. ; We are getting the first digit of a parameter, a quoted string,
  332. ; a ;, or a command.
  333. f_get_param:
  334.     lodsb
  335.     cmp    al, '0'
  336.     jb    fgp_may_quote
  337.     cmp    al, '9'
  338.     ja    fgp_may_semi
  339.     ; It's the first digit.  Initialize current parameter with it.
  340.     sub    al,'0'
  341.     cmp    bx, param_end
  342.     adc    bx, 0            ; if bx<param_end bx++;
  343.     mov    byte ptr cs:[bx], al
  344.     next_is f_in_num
  345.  
  346. fgp_may_quote:
  347.     cmp    al, '"'
  348.     jz    fgp_isquote
  349.     cmp    al, "'"
  350.     jnz    syntax_error
  351.  
  352. fgp_isquote:
  353.     mov    cs:string_term, al    ; save it for end of string
  354.     next_is f_get_string        ; and read string into param_buffer
  355.  
  356. fgp_may_semi:
  357.     cmp    al, ';'
  358.     jnz    call_cmd             ; jump to code shared with f_in_num
  359.     cmp    bx, param_end
  360.     adc    bx, 0            ; if bx<param_end bx++;
  361.     mov    cs:[bx],dh
  362.     next_is    f_get_param
  363.  
  364. ;------ f_in_num -------------------------------------
  365. ; Last character was a digit.
  366. ; Looking for more digits, a semicolon, or a command character.
  367. f_in_num:
  368.     lodsb
  369.     cmp    al, '0'
  370.     jb    syntax_error
  371.     cmp    al, '9'
  372.     ja    fgp_semi_or_cmd
  373.     ; It's another digit.  Add into current parameter.
  374.  
  375.     sub    al,'0'
  376.     push    dx
  377.     mov    dl,byte ptr cs:[bx]
  378.     shl    dx,1        ;mul    dx,10
  379.     add    ax,dx        ;add    ax,dx
  380.  
  381.     if    is_8088
  382.     shl    dx,1
  383.     shl    dx,1
  384.     else
  385.     shl    dx,2
  386.     endif
  387.  
  388.     add    ax,dx
  389.     mov    byte ptr cs:[bx],al
  390.     pop    dx
  391.  
  392.     next_is f_in_num
  393.  
  394. fgp_semi_or_cmd:
  395.     cmp    al, ';'
  396.     jnz    call_cmd
  397.     next_is f_get_param
  398.  
  399. ;----- syntax_error ---------------------------------------
  400. ; A character was rejected by the state machine.  Exit to
  401. ; main loop, and print offending character.  Let main loop
  402. ; decrement CX (length of input string).
  403.  
  404. syntax_error:
  405.     mov    cs:escvector, 0
  406.     mov    ah, cs:cur_attrib
  407.     jmp    f_control        ; exit, print offending char
  408.  
  409. ;----- call_cmd ---------------------------------------------
  410. ; Character in AL isn't a paramater or delimiter, so
  411. ; either call the appropriate command or abort with
  412. ; a syntax error.
  413.  
  414. call_cmd:
  415.     ; It must be a command letter.
  416.     cmp    al, '@'
  417.     jb    syntax_error
  418.     cmp    al, 'Z'
  419.     jbe    fgp_is_cmd
  420.     cmp    al, 'z'
  421.     ja    syntax_error
  422.     cmp    al, 'a'
  423.     jb    syntax_error
  424.     ; It's a lower-case command letter.
  425.     ; Remove hole between Z and a to save space in table.
  426.     sub    al, 'a'-'['
  427. fgp_is_cmd:
  428.     ; It's a command letter.  Save registers, convert letter
  429.     ; into address of routine, set up new register usage, call routine.
  430.     push    si            ; These three registers hold info
  431.     push    cx            ; having to do with the input string,
  432.     push    ds            ; which has no interest at all to the
  433.                     ; control routine.
  434.     push    cs
  435.     pop    ds            ; ds is now cs
  436.  
  437.     cbw                ; zero ah
  438.     mov    cx, bx
  439.     mov    si, param_buffer    ; si is now pointer to parameters
  440.     sub    cx, si            ; cx is now # of parameters
  441.     inc    cx
  442.  
  443.     mov    bh,ah
  444.     shl    ax,1
  445.     ; ax is now pointer to command routine address in table
  446.  
  447.     xchg    bx,ax            ; save pointer to routine in bx
  448.  
  449.     ; Calculate cur_x from DX.
  450.     mov    al, max_x
  451.     sub    al, dl
  452.     mov    cur_x, al
  453.  
  454.     ; Get first parameter into AX; if defaulted, set it to 1.
  455.     lodsb
  456.     cmp    al,1            ; if ax<1 ax++;
  457.     adc    al,ah
  458.     ; Finally, call the command subroutine.
  459.     call    word ptr (ansi_fn_table-2*'@')[bx]
  460.  
  461.     pop    ds
  462.     pop    cx
  463.     pop    si
  464.  
  465.     mov    ax, cs:string_attrib    ; Prepare for STOSW.
  466.     mov    cs:escvector, 0     ; No longer parsing escape sequence.
  467.     ; Re-enter at bottom of main loop.
  468.     jmp    f_looploop
  469.  
  470.  
  471. code    ends
  472.     end
  473.