home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SCREEN / ZAVT11.ZIP / ZAVT_F.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-05-28  |  18.0 KB  |  693 lines

  1. page    58,132
  2. ;----- zavt_f.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. ; Each routine is called with the following register usage:
  9. ;  AX = max(1, value of first parameter)
  10. ;  Z flag is set if first parameter is zero.
  11. ;  CX = number of paramters
  12. ;  SI = offset of second parameter from CS
  13. ;  DS = CS
  14. ;  ES:DI points to the current location on the memory-mapped screen.
  15. ;  DX is number of characters remaining on the current screen line.
  16. ; The control routine is free to trash AX, BX, CX, SI, and DS.
  17. ; It must preserve ES, and can alter DX and DI if it wants to move the
  18. ; cursor.
  19. ;
  20. ; Revisions
  21. ;----------------------------------------------------------------
  22. ; Luns Tee, Toronto Ontario
  23. ;
  24. ; 19 Dec 1988:    Replaced 43 line code with code to set max_y to current
  25. ;        length of screen
  26. ;
  27. ; 8 Mar 1989:    Moved code to set max_y to ZANSI.ASM where code to
  28. ;        set max_x is
  29. ;
  30. ; 24 Mar 1989:    Added pseudo cursor switching a la NANSI24. SM 45
  31. ;        enables, RM 45 disables.
  32. ;
  33. ; 23 Aug 1989:    Now variable length output from DSR - 1 to 3 digits
  34. ;        rather than a rigid two as before
  35. ;
  36. ; 28 Aug 1989:    Added support for unimplemented EID and EIL functions
  37. ;        and added blitz versions to be used in text mode -
  38. ;        faster, but as functions are infrequently used, not
  39. ;        significant
  40. ;
  41. ; 17 Sep 1989:    Added SGR2 as bold off conforming to DOS "standard"
  42. ;        and let DSR respond only to 6n
  43. ;----------------------------------------------------------------
  44.     include    zavt_d.asm        ; get equates
  45.  
  46.     ; To zavt_p.asm
  47.     public    ansi_fn_table
  48.  
  49.     ; From zavt.asm
  50.     extrn    pseudo_flag:byte, wrap_flag:byte
  51.     extrn    gmode_flag:byte
  52.     extrn    port_6845:word
  53.     extrn    cur_coords:word, saved_coords:word
  54.     extrn    cur_x:byte, max_x:byte
  55.     extrn    cur_y:byte, max_y:byte
  56.     extrn    max_coords:word
  57.     extrn    cur_attrib:byte
  58.     extrn    xy_to_regs:near
  59.     extrn    get_blank_attrib:near
  60.     extrn    cpr_esc:byte, cpr_buf:byte, cprseq:keybuf
  61.     extrn    video_mode:byte
  62.     extrn    screen_len:word
  63.     extrn    cur_page:byte, video_off:word
  64.  
  65.     if    xlate
  66.     public    key_init
  67.  
  68.     extrn    lookup:near
  69.     extrn    param_end:word, redef_end:abs
  70.     extrn    param_buffer:abs
  71.     extrn    xlatseq:keybuf
  72.     else
  73.     extrn    param_end:abs
  74.     endif
  75.  
  76. code    segment byte public 'CODE'
  77.     assume cs:code, ds:code
  78.  
  79. ;----- byteout ---------------------------------------------------
  80. ; Converts al to a decimal ASCII string (in 0..255),
  81. ; stores it at ES:DI++.  Returns DI pointing at byte after last digit.
  82. ; Destroys BX.
  83.  
  84. byteout proc    near
  85.     aam                ; ones in al, tens in ah
  86.     mov    bx,ax            ;   "   " bl,   "   " bh
  87.     mov    al,ah            ; tens in al
  88.     aam                ; hundreds in ah
  89.     or    ah,ah            ; <99?
  90.     jz    tens            ; if so, drop first digit
  91.     xchg    al,ah            ; put hundreds in al, tens in ah
  92.     add    al,30h            ; "0" base
  93.     stosb                ; store it
  94.     mov    al,bl            ; restore ones
  95.                     ; and make sure we print both remaining
  96. twodigit:
  97.     xchg    al,ah            ; tens in al, ones in ah
  98.     add    ax,3030h        ; "00" base
  99.     stosw                ; store them
  100.     ret
  101.  
  102. tens:    mov    ax,bx            ; ones in al, tens in ah
  103.     or    ah,ah            ; <9?
  104.     jnz    twodigit        ; skip another digit
  105. onedigit:
  106.     add    al,30h            ; "0" base
  107.     stosb                ; store it
  108.     ret
  109. byteout endp
  110.  
  111. ;----- ansi_fn_table -----------------------------------
  112. ; Table of offsets of terminal control subroutines in order of
  113. ; the character that invokes them, @..Z, a..z.    Exactly 53 entries.
  114. ; All the subroutines are defined below in this module.
  115. ansi_fn_table    label    word
  116.     dw    ic,  cup, cdn, cfw, cbk     ; @, A, B, C, D
  117.     dw    nul, nul, nul, hvp, nul     ; E, F, G, H, I
  118.     dw    eid, eil, il,  d_l, nul     ; J, K, L, M, N
  119.     dw    nul, dc,  nul, nul, nul     ; O, P, Q, R, S
  120.     dw    nul, nul, nul, nul, nul     ; T, U, V, W, X
  121.     dw    nul, nul            ; Y, Z
  122.     dw    nul, nul, nul, nul, nul     ; a, b, c, d, e
  123.     dw    hvp, nul, sm,  nul, nul     ; f, g, h, i, j
  124.     dw    nul, rm,  sgr, dsr, nul     ; k, l, m, n, o
  125.     dw    key, nul, nul, scp, nul     ; p, q, r, s, t
  126.     dw    rcp, nul, nul, nul, nul     ; u, v, w, x, y
  127.     dw    nul                ; z
  128.  
  129. ;-------- Color table -----------------------------------------
  130. ; Used in "set graphics rendition"
  131. colors    equ    23            ; number of colors in table
  132. color_table:
  133.     db    0, 000h,07h        ; all attribs off; normal.
  134.     db    1, 0ffh,08h        ; bold
  135.     db    2, 0f7h,00h        ; bold off
  136.     db    4, 0f8h,01h        ; underline
  137.     db    5, 0ffh,80h        ; blink
  138.     db    7, 0f8h,70h        ; reverse
  139.     db    8, 088h,00h        ; invisible
  140.  
  141.     db    30,0f8h,00h        ; black foreground
  142.     db    31,0f8h,04h        ; red
  143.     db    32,0f8h,02h        ; green
  144.     db    33,0f8h,06h        ; yellow
  145.     db    34,0f8h,01h        ; blue
  146.     db    35,0f8h,05h        ; magenta
  147.     db    36,0f8h,03h        ; cyan
  148.     db    37,0f8h,07h        ; white
  149.  
  150.     db    40,08fh,00h        ; black background
  151.     db    41,08fh,40h        ; red
  152.     db    42,08fh,20h        ; green
  153.     db    43,08fh,60h        ; yellow
  154.     db    44,08fh,10h        ; blue
  155.     db    45,08fh,50h        ; magenta
  156.     db    46,08fh,30h        ; cyan
  157.     db    47,08fh,70h        ; white
  158.  
  159. ansi_functions    proc    near        ; set return type to NEAR
  160.  
  161. ;----- Cursor Motion -----------------------------------------------
  162.  
  163. ;-- cursor to y,x
  164. hvp:    dec    ax        ; Convert to zero-based coordinates.
  165.     mov    cur_y,al
  166.     ; Get second parameter, if it is there, and set X with it.
  167.     mov    al,ah
  168.     cmp    cx,2        ; was there a second parameter?
  169.     jb    hvp_xok
  170.     lodsb            ; yes.
  171.     cmp    al,1
  172.     adc    al,ah
  173.     dec    ax        ; convert to zero-based coordinates.
  174. hvp_xok:mov    cur_x,al
  175.  
  176.     ; Clip to maximum coordinates.
  177. hvp_set:
  178.     mov    ax, max_coords    ; ah = x, al = y
  179.     dec    ah
  180.     cmp    ah, cur_x
  181.     jae    hvp_sxok
  182.     mov    cur_x, ah
  183. hvp_sxok:
  184.     cmp    al, cur_y
  185.     ja    hvp_syok
  186.     mov    cur_y, al
  187. hvp_syok:
  188.     ; Set values of DX and DI accordingly.
  189.     call    xy_to_regs
  190.  
  191.     ret
  192.  
  193. ;-- cursor forward --
  194. cfw:    add    cur_x, al
  195.     jmp    hvp_set
  196.  
  197. ;-- cursor back -----
  198. cbk:    sub    cur_x, al
  199.     jae    hvp_set
  200.     mov    cur_x, ah
  201.     jmp    hvp_set
  202.  
  203. ;-- cursor down -----
  204. cdn:    add    cur_y, al
  205.     jmp    hvp_set
  206.  
  207. ;-- cursor up -------
  208. cup:    sub    cur_y, al
  209.     jae    hvp_set
  210.     mov    cur_y, ah
  211.     jmp    hvp_set
  212.  
  213. ;-- save cursor position --------------------------------------
  214. scp:    mov    ax, cur_coords
  215.     mov    saved_coords, ax
  216.     ret
  217.  
  218. ;-- restore cursor position -----------------------------------
  219. rcp:    mov    ax, saved_coords
  220.     mov    cur_coords, ax
  221.     jmp    hvp_set     ; Clip in case we have switched video modes.
  222.  
  223. ;-- set graphics rendition ------------------------------------
  224. ; Modifies the color in which new characters are written.
  225.  
  226. sgr:    dec    si        ; get back pointer to first parameter
  227.     cmp    cx,1        ; Did he give any parameters?
  228.     adc    cl,ah         ; no parameters, so fake
  229.                 ; one with the default value.
  230.  
  231. sgr_loop:            ; Handles each parameter
  232.     lodsb            ; al = next parameter
  233.     push    cx
  234.     mov    cx,colors
  235.     mov    bx,offset color_table - 3
  236. sgr_search:
  237.     add    bx,3
  238.     cmp    al,[bx]
  239.     loopne    sgr_search    ; until match found or done
  240.     jne    sgr_loopx
  241.  
  242.     ; If parameter named a known color, set the current color variable.
  243.     mov    bx,1[bx]
  244.     mov    al,cur_attrib
  245.     and    al,bl
  246.     or    al,bh
  247.     mov    cur_attrib,al
  248. sgr_loopx:
  249.     pop    cx
  250.     loop    sgr_loop    ; until no more parameters.
  251.     ret
  252.  
  253. ;-- Insert / Delete Characters ----------------------------
  254. ; AL is number of characters to insert or delete. AH=0
  255. ; Preserves DX, DI; does not move cursor.
  256.  
  257. ic:    dec    ah            ; 1 => swap dest & source below
  258.  
  259. dc:    ; AL = number of chars to ins or del (guarenteed nonzero).
  260.     ; Limit him to # of chars left on line.
  261.     cmp    al,dl
  262.     jbe    dc_cok
  263.     mov    al,dl
  264. dc_cok:
  265.     mov    cl,al            ; CX gets # of chars to ins/del
  266.     mov    ch,dh            ; make it a word
  267.     mov    bp,cx            ; BP gets # of columns to clear.
  268.  
  269.     ; Set up source = destination + cx*2, count = dx - cx
  270.     mov    si,di
  271.     add    si,cx
  272.     add    si,cx
  273.     neg    cl
  274.     add    cl,dl            ; CX = # of words to transfer
  275.  
  276.     ; If this is an insert, then flip transfer around in both ways.
  277.     or    ah,ah
  278.     jz    DC_CH_DO
  279.     xchg    di,si        ; source <-> dest
  280.     std            ; up <-> down
  281.     mov    ax,cx        ; make move over same range
  282.     dec    ax
  283.     shl    ax, 1        ; AX=dist from 1st to last byte.
  284.     add    di,ax        ; Start transfer at high end of block
  285.     add    si,ax        ;  instead of low end.
  286. DC_CH_DO:
  287.     cmp    cs:gmode_flag,ch
  288.     jnz    gmode_idc    ; if in graphics mode, leave
  289.  
  290.     push    es
  291.     pop    ds
  292.     rep    movsw        ; Move those characters.
  293.     push    cs
  294.     pop    ds
  295.  
  296.     mov    cx,bp        ; fetch chars to blank
  297. blankit:
  298.     call    get_blank_attrib; get attribute in ah
  299.     mov    al," "        ; and space in al
  300.     rep    stosw        ; blank out region
  301.     cld            ; clear direction flag before continuing
  302.     call    xy_to_regs    ; and restore DI,DX
  303. gmode_idc:
  304.     ret
  305.  
  306. ;== erase in line ================================================
  307. eil:    dec    si
  308.     lodsb            ; get the real parameter
  309.     if    direct_scroll
  310.     cmp    gmode_flag,ah
  311.     jnz    eil_slow
  312.  
  313. ;--- fast_eil ------------
  314.     cmp    al,1
  315.     jbe    fast_eil_partscreen; 2K - erase whole line
  316.     std            ; work backwards
  317.     mov    ch,ah
  318.     mov    cl,max_x    ; max_x characters
  319.     mov    ax,dx        ; ax now chars to eol
  320.     dec    ax        ; less one
  321.     shl    ax,1        ; bytes to eol
  322.     add    di,ax        ; start from end of line
  323.     jmp    short blankit
  324.  
  325. fast_eil_partscreen:
  326.     jb    fast_to_eol    ; 1K - erase to cursor
  327.     std            ; work backwards
  328.     mov    cl,cur_x    ; cur_x spaces backwards
  329.     inc    cx        ; include character under cursor
  330.     jmp    short blankit
  331.  
  332. fast_to_eol:            ; 0K - erase from cursor
  333.     mov    cx,dx
  334.     jmp    short blankit
  335.     endif
  336.  
  337. ;---- bios_eil -----------
  338. eil_slow:
  339.     push    dx        ; save count to eol
  340.     mov    cl,ah        ; left margin
  341.     mov    ch,cur_y    ; set row pointer for
  342.     mov    dh,ch        ; both corners of scroll region
  343.     mov    dl,max_x    ; right margin
  344.     dec    dx
  345.  
  346.     cmp    al,1        ; 2K - whole line?
  347.     ja    scrollem    ; yes, blank it
  348.     jb    eil_from_cursor    ; 1K - erase up to cursor
  349.     mov    dl,cur_x    ; point right side at cursor
  350.     jmp    short scrollem    ; and blank it
  351.  
  352. eil_from_cursor:
  353.     mov    cl,cur_x    ; set left corner of scroll region
  354.     jmp    short scrollem    ; to cursor location and blank
  355.  
  356. ;== erase in display ========================================================
  357. eid:    dec    si
  358.     lodsb            ; get the real parameter
  359.     if    direct_scroll
  360.     cmp    gmode_flag,ah
  361.     jnz    eid_slow
  362.  
  363. ;--- fast_eid ------------
  364.     cmp    al,1        ; 2J - clear screen and home cursor
  365.     jbe    fast_partscreen
  366.     mov    cur_coords,0    ; home the cursor
  367.     call    xy_to_regs    ; set up DI and DX accordingly
  368.     mov    cx,screen_len    ; get size of screen in CX
  369.     shr    cx,1        ; make it a word count
  370.     jmp    short blankit
  371.  
  372. fast_partscreen:
  373.     jb    fast_from_cursor; 1J - erase screen up to cursor
  374.     std            ; work backwards
  375.     mov    cx,di        ; get pointer to word on screen
  376.     sub    cx,video_off    ; and subtract start of screen
  377.     shr    cx,1        ; to get count in words of area
  378.     inc    cx        ; to clear
  379.     jmp    short blankit    ; then clear it
  380.  
  381. fast_from_cursor:
  382.     mov    cx,video_off    ; get start of screen
  383.     add    cx,screen_len    ; point to end of screen
  384.     sub    cx,di        ; and subtract pointer from it
  385.     shr    cx,1        ; to get count in words
  386.     jmp    short blankit    ; then blank
  387.     endif
  388.  
  389. ;--- slow_eid ------------
  390. eid_slow:
  391.     push    dx        ; preserve count to eol
  392.     mov    dx,max_coords    ; point to bottom right
  393.     xchg    dl,dh        ; corner (make adjustments
  394.     dec    dx        ; for column being 1 based
  395.     cmp    al,1
  396.     jbe    eid_partscreen    ; 2J clear screen
  397.     xor    cx,cx        ; point to top right corner
  398.     mov    cur_coords,cx    ; put cursor there
  399.     pop    dx        ; trash saved count to eol
  400.     call    xy_to_regs    ; (doesn't modify CX)
  401.     push    dx        ; use new one instead
  402.     mov    dh,max_y
  403.  
  404. scrollem:
  405.     call    get_blank_attrib    ; get attribute
  406.     mov    bh,ah        ; in bh
  407.     mov    ax,600h        ; blank the screen
  408.     int    10h
  409. noscroll:
  410.     pop    dx        ; restore count to eol
  411.     ret
  412.  
  413. eid_partscreen:
  414.     call    eil_slow    ; blank what there is of the current line
  415.     xor    cx,cx        ; point to upper left corner
  416.     cmp    byte ptr [si-1],cl
  417.     jz    eid_from_cursor    ; 1K
  418.     mov    dh,cur_y    ; make line above current line bottom of
  419.     jmp    short check_overlap    ; scroll region (dec dh later)
  420.  
  421. eid_from_cursor:
  422.     mov    ch,cur_y    ; 0K - line below current line
  423.     inc    ch        ; top of scroll region
  424.     inc    dh        ; lower bottom for check
  425. check_overlap:
  426.     cmp    ch,dh        ; overlap?
  427.     jz    noscroll    ; then don't scroll
  428.     dec    dh        ; else restore bottom
  429.     jmp    scrollem    ; and scroll region
  430.  
  431. ;-- device status report --------------------------------
  432. ; Stuffs an escape, a left bracket, current Y, semicolon, current X,
  433. ; a capital R, and a carriage return into input stream.
  434. ; The coordinates are 1 to 3 decimal digits each.
  435.  
  436. dsr:    cmp    al,6        ; must be 6n
  437.     jnz    dsr_out
  438.     push    di
  439.     push    es
  440.     mov    ax,cs
  441.     mov    es,ax
  442.     mov    di,offset cpr_buf
  443.     mov    al,cur_y
  444.     inc    ax        ; convert to one-based coords
  445.     call    byteout     ; row
  446.     mov    al,';'
  447.     stosb
  448.     mov    al,cur_x
  449.     inc    ax        ; convert to one-based coords
  450.     call    byteout     ; column
  451.     mov    ax,13*256+'R'    ; R ANSI function 'Cursor Position Report'
  452.     stosw
  453.     mov    ax,di
  454.     dec    ax
  455.     mov    word ptr cprseq.adr, ax    ; save pointer to last char in string
  456.     sub    ax,offset cpr_esc    ; di is # of characters in string
  457.     mov    word ptr cprseq.len,ax    ; pass info to the getchar routine
  458.     pop    es
  459.     pop    di
  460. dsr_out:
  461.     ret
  462.  
  463. ;---- Delete/Insert Lines -------------------------------
  464. ; AL is number of lines to delete/insert. AH=0
  465. ; Preserves DX, DI; does not move cursor.
  466.  
  467. d_l:    ; Delete lines.
  468.     dec    ah            ; BIOS: scroll up
  469.  
  470. il:    ; Insert lines.
  471.     add    ah, 7            ; BIOS: scroll down
  472.  
  473. il_open:
  474.     ; Whether inserting or deleting, limit him to (max_y - cur_y) lines;
  475.     ; if above that, we're just clearing; set AL=0 so BIOS doesn't burp.
  476.     mov    bh, max_y
  477.     sub    bh, cur_y
  478.     cmp    al, bh
  479.     jbe    il_ok            ; DRK 9/4...
  480.     mov    al,dh            ; he tried to move too far
  481. il_ok:
  482.     push    ax
  483.     call    get_blank_attrib
  484.     mov    bh, ah            ; color to use on new blank areas
  485.     pop    ax            ; AL is number of lines to scroll.
  486.  
  487.     mov    cl,dh            ; upper-left-x of data to scroll
  488.     mov    ch, cur_y        ; upper-left-y of data to scroll
  489.     push    dx
  490.     mov    dx, max_coords        ; lower-right-x
  491.     xchg    dh, dl            ; lower-right-y (zero based)
  492.     dec    dx
  493.     int    10h            ; call BIOS to scroll a rectangle.
  494.     pop    dx
  495.     ;fall through to a way back
  496.  
  497. ;----- nul ---------------------------------------------
  498. ; No-action ansi sequence; called when unknown command given.
  499. nul:    ret                ; done.
  500.  
  501. ;---- set / reset mode ---------------------------------------
  502. ; Sets graphics/text mode; also sets/resets "no wrap at eol" mode.
  503.  
  504. sm:    dec    ah        ; set
  505.  
  506. rm:    mov    bx, offset wrap_flag
  507.     cmp    al, 7        ; Wrap/nowrap?
  508.     jz    sm_flag
  509.     mov    bx, offset pseudo_flag
  510.     cmp    al, 45        ; Graphics cursor or not?
  511.     jz    sm_flag
  512.  
  513.     ;--- Set Video Mode ---
  514.     ; It must be a video mode.  Call BIOS.
  515.  
  516.     dec    si
  517.     lodsb            ; in case mode chosen is zero
  518.     mov    ah,dh        ; "set video mode"
  519.     int    10h
  520.  
  521.     ; Read the BIOS buffer address/cursor position variables.
  522.     mov    ax,abs40
  523.     mov    ds,ax
  524.     assume    ds:abs40
  525.  
  526.     ; Find current video mode and screen size.
  527.     mov    ax, crt_len
  528.     mov    cs:screen_len, ax
  529.  
  530.     mov    ax,word ptr crt_mode    ; al = crt mode; ah = # of columns
  531.     mov    cs:max_x, ah
  532.  
  533.     mov    bx,0B800h        ; segment for colour card
  534.     cbw
  535.     cmp    al,4
  536.     jb    text_mode
  537.     mov    bh,0B8h            ; but if not colour text, it's mono
  538.     cmp    al,7
  539.     jz    text_mode
  540.     dec    ah
  541. text_mode:
  542.     mov    es,bx
  543.     mov    word ptr cs:video_mode,ax
  544.  
  545.     mov    al, crt_rows
  546.     mov    cs:max_y,al
  547.  
  548.     ; Find current cursor page.
  549.     mov    al,active_page
  550.     mov    cs:cur_page,al
  551.  
  552.     ; Find video buffer segment address; adjust so ofs is 0; return in AX.
  553.     mov    ax,crt_start
  554.     mov    cs:video_off,ax
  555.     mov    ax,addr_6845        ; 6845 address
  556.  
  557.     push    cs
  558.     pop    ds
  559.     assume    ds:code
  560.  
  561.     mov    port_6845,ax
  562.  
  563.     mov    cur_coords,0
  564.     call    xy_to_regs
  565.     ret
  566.  
  567.     ;--- Set or reset simple flag ---
  568. sm_flag:
  569.     mov    [bx], ah
  570.     ret
  571.  
  572. ;-- keyboard reassignment -------------------------------------------
  573. ; Key reassignment buffer is between param_end and redef_end+2, exclusive.
  574. ; When it shrinks or grows, param_end is moved.
  575. ; Format of an entry is as follows:
  576. ;   highest address -> length:word (may be 0)
  577. ;               key to replace:word     (either hi or low byte is zero)
  578. ;                          .
  579. ;                          .    new key value, "length" bytes long
  580. ;                          .
  581. ;   lowest address  -> next entry, or free space.
  582. ; If no arguments are given, keyboard is reset to default condition.
  583. ; Otherwise, first parameter (or first two, if first is zero) defines
  584. ; the key whose value is to be changed, and the following parameters
  585. ; define the key's new, possibly zero-length, value.
  586.  
  587.     if    xlate
  588. key:
  589.     ; Is this a reset?
  590.     or    cx, cx
  591.     jz    key_init
  592.     ; Get the first (or first two) parameters
  593.     cld
  594.     dec    si
  595.     mov    ax,[si]    ; get two params
  596.     dec    cx    ; first param isn't in string
  597.     add    si,cx    ; point si to end of string
  598.  
  599.     or    al, al    ; Is it a function key?
  600.     jnz    key_notfnkey
  601.  
  602.     or    cx,cx    ; It's a function key
  603.     jz    key_init; if only a zero passed, take it as a reset
  604.     dec    cx
  605. key_notfnkey:
  606.  
  607.     ; Key to redefine now in AX.  If it's already redefined,
  608.     ; lookup will set Z, point SI to redef string, set CX to its length.
  609.     push    di
  610.     push    es
  611.     push    cx
  612.     push    si
  613.  
  614.     std            ; moving up, must move from top down
  615.     push    ds
  616.     pop    es        ; string move must have ES=DS
  617.     call    lookup        ; rets Z if redefined...
  618.     jnz    key_newkey
  619.  
  620.     ; It's already defined.  Erase its old definition- i.e., move
  621.     ; region param_end+1..SI-CX upwards CX+4 bytes, add CX+4 to param_end.
  622.  
  623.     sub    si,cx
  624.     mov    di,si
  625.     add    cx,4
  626.     add    param_end,cx
  627.     add    di,cx
  628.  
  629.     ; adjust the xlatseq pointer
  630.     mov    bx, xlatseq.adr
  631.     cmp    bx, di        ; in area above deleted entry
  632.     ja    del_def        ; so nothing to do
  633.     add    xlatseq.adr, cx    ; else move pointer upwards
  634.     cmp    bx, si        ; was it the deleted entry?
  635.     jb    del_def
  636.     mov    xlatseq.len, 0    ; if so, null the sequence
  637. del_def:
  638.     rep    movsb
  639. key_newkey:
  640.     ; Key not redefined.  See if there's enough room to redefine it.
  641.     pop    si        ; get back pointer to redef string
  642.     pop    cx        ; get back number of bytes in redef string
  643.     mov    di, param_end    ; hi byte of new redef record, hi byte of len
  644.     sub    di, 3        ; low byte of new redef index
  645.     mov    bx, di
  646.     sub    bx, 17        ; better be at least 16 bytes room
  647.     cmp    bx, si
  648.     jb    key_popem    ; nope- forget it.
  649.     ; Nothing in the way now!
  650.     mov    [di+2], cx    ; save length field
  651.     stosw
  652.     inc    di        ; adjust for descending pointer
  653.     rep    movsb        ; copyit
  654.     mov    param_end, di    ; save adr of new hi byte of free area
  655. key_popem:
  656.     pop    es
  657.     pop    di
  658.     cld
  659.     ret
  660.  
  661. key_init:
  662.     ; Build the default redefinition table:
  663.     ;    control-printscreen -> control-P
  664.     push    es
  665.  
  666.     push    ds
  667.     pop    es
  668.  
  669.     std
  670.     mov    di, redef_end
  671.     mov    ax, 1
  672.     stosw
  673.     mov    ax, 7200h    ; control-printscreen
  674.     stosw
  675.     inc    di
  676.     mov    al, 16        ; control P
  677.     stosb
  678.     mov    param_end, di    ; save new bottom of redef table
  679.     pop    es
  680.     cld
  681.     ret
  682.  
  683.     else
  684. key    equ    offset nul
  685.     endif
  686.  
  687. ansi_functions    endp    ; end dummy procedure block
  688.  
  689.  
  690. code    ends
  691.     end
  692.  
  693.