home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msuapr.asm < prev    next >
Assembly Source File  |  2020-01-01  |  58KB  |  1,199 lines

  1.         NAME    msugen
  2. ; File MSUAPR.ASM
  3. ; Kermit action verbs tied to Apricot funtion keys 26.04.88 [rwtc]
  4. ;
  5. ; Keyboard translator, by Joe R. Doupnik, Dec 1986
  6. ;  with contributions from David L. Knoell.
  7. ; For Generic keyboard reading (via DOS)
  8. ; edit history:
  9. ; Last edit 1 Jan 1988
  10. ; 1 Jan 1988 version 2.30
  11.  
  12.         include mssdef.h
  13.  
  14.         public  keybd, dfkey, shkey, msuinit
  15.  
  16. ; some definitions
  17.  
  18. maxkeys equ     128                     ; maximum number of key definitions
  19. maxstng equ     64                      ; maximum number of multi-char strings
  20. stbuflen equ    1000                    ; length of string buffer (bytes)
  21.  
  22. verb    equ     8000h                   ; dirlist flag: use verb action table
  23. strng   equ     4000h                   ; dirlist flag: use string action table
  24. scan    equ     100h                    ; keycode flag: code is scan not ascii
  25. braceop equ     7bh                     ; opening curly brace
  26. bracecl equ     7dh                     ; closing curly brace
  27.  
  28. datas   segment public 'datas'
  29.         extrn taklev:byte, comand:byte, intake:byte, flags:byte
  30.         extrn shkadr:word, stkadr:word, trans:byte
  31.                                                 ; system dependent references
  32.  
  33. ;;;     System Independent local storage
  34.  
  35. tranbuf db      132 dup (?)             ; 132 byte translator work buffer
  36. crlf    db      cr,lf,'$'
  37. dfhelp1 db    cr,lf,' Enter key',27h,'s identification as a character',cr,lf
  38.         db      '  or as its numerical equivalent \{b##} of ascii',cr,lf
  39.         db      '  or as its scan code \{b##}'
  40.         db      cr,lf,'  or as SCAN followed by its scan code',cr,lf
  41.         db      '    where b is O for octal, X for hex, or D for decimal'
  42.         db      ' (default).',cr,lf,'    Braces {} are optional.'
  43.         db      cr,lf,'    Follow the identification with the new definition.'
  44.         db      cr,lf,' or CLEAR to restore initial key settings.$'
  45. dfaskky db      cr,lf,' Push key to be defined: $'
  46. dfaskdf db      ' Enter new definition: $'
  47. verbbad db      cr,lf,' No such verb',cr,lf,'$'
  48. strbad  db      cr,lf,' Not enough space for new string',cr,lf,'$'
  49. keyfull db      cr,lf,' No more space to define keys',cr,lf,'$'
  50. dfkopps db      cr,lf,' Opps! That is Kermit',27h,'s Escape Char.'
  51.         db      ' Translation is not permitted.',cr,lf,'$'
  52. shkmsg1 db      cr,lf,'Push key to be shown (? shows all): $'
  53. shkmsg2 db      ' decimal is defined as',cr,lf,'$'
  54. shkmsg3 db      cr,lf,'... more, push any key to continue ...$'
  55. kwarnmsg db     cr,lf,' Notice: this form of Set Key is obsolete$'
  56.  
  57. ascmsg  db      ' Ascii char: $'
  58. scanmsg db      ' Scan Code $'
  59. strngmsg db     ' String: $'
  60. verbmsg db      ' Verb: $'
  61. noxmsg  db      ' Self, no translation.$'
  62. fremsg  db      cr,lf,' Free space: $'
  63. kyfrdef db      ' key and $'
  64. stfrdef db      ' string definitions, $'
  65. stfrspc db      ' string characters.',cr,lf,'$'
  66.                                         ; translation tables
  67. keylist dw      maxkeys dup (0)         ; 16 bit keycodes, paralled by dirlist
  68. dirlist dw      maxkeys dup (0)         ; director {v+s} + {index | new char}
  69. sptable dw      maxstng dup (0)         ; list of asciiz string offsets
  70. stbuf   dw      stbuflen dup (0)        ; buffer for strings
  71. strmax  dw      stbuf                   ; first free byte in stbuf
  72. listptr dw      0                       ; item number for keylist and dirlist
  73. nkeys   dw      0                       ; number of actively defined keys
  74. keycode dw      0                       ; ascii/scan code for key
  75. kbtemp  dw      0                       ; scratch storage for translator
  76. brace   db      0                       ; brace detected flag byte
  77. oldform db      0                       ; old form Set Key, if non-zero
  78. verblen dw      0                       ; length of user's verb (work temp)
  79. kwcnt   dw      0                       ; number of keywords (work temp)
  80. msutake db      0                       ; if being run from take file or not
  81. twelve  dw      12d
  82.  
  83. ;;;     End System Independent Data Area
  84.  
  85. ;;;     System Dependent Data Area
  86. ;       edit dfhelp2 to include nice list of verbs for this system.
  87. dfhelp2 db      cr,lf,' Enter either \{Kverb}  for a Kermit action verb',cr,lf
  88.         db      ' or a replacement string  (single byte binary numbers are'
  89.         db      ' \{b##})',cr,lf,' or nothing at all to undefine a key.'
  90.         db      cr,lf,' Braces {} are optional, and strings maybe enclosed in'
  91.         db      ' them.',cr,lf,' Strings may not begin with the character'
  92.         db      ' combinations of  \k  or  \{k',cr,lf
  93.         db      '    (start with a { brace instead).',cr,lf,lf
  94.         db      ' Verbs are as follows:',cr,lf
  95.         db      ' Logoff (suspend logging), Logon (resume logging),'
  96.         db      ' DOS (push to), null (send a)',cr,lf
  97.         db      ' break, help, prtscn, status, exit'
  98.         db      cr,lf,'$'
  99.  
  100.         ; Aliaskey: keys having aliases - same ascii code but more than one
  101.         ; scan code, as on auxillary keypads. Use just scan codes with these.
  102.         ; Alternative use: force ascii keys to report out just scan codes.
  103.         ; Table format: high byte = scan code, low byte = ascii code.
  104.         ; Contents are machine dependent.
  105. aliaskey db     0
  106. aliaslen equ    ($-aliaskey) shr 1      ; number of words in aliaskey table
  107.  
  108. kverbs  db      10                      ; number of table entries below
  109.         mkeyw   'prtscn',trnprs         ; independent of ordering and case!
  110.         mkeyw   'break',sendbr          ; mkeyw 'name',procedure entry point
  111.         mkeyw   'Hangup',chang
  112.         mkeyw   'null',snull
  113.         mkeyw   'help',cquery
  114.         mkeyw   'status',cstatus
  115.         mkeyw   'exit',cquit
  116.         mkeyw   'DOS',kdos
  117.         mkeyw   'Logoff',klogof
  118.         mkeyw   'Logon',klogon
  119.                                 ; Initialization data.
  120. kbdinlst equ    this byte     ; Kermit IBM initialization time keyboard setup
  121.         mkeyw   '\x7f',8        ; Backspace key sends DEL
  122.         mkeyw   '\Khelp',177        ; F1
  123.         mkeyw   '\Kbreak',178           ; F2
  124.         mkeyw   '\Kstatus',179        ; F3
  125.         mkeyw   '\Kdos',180        ; F4
  126.         mkeyw   '\Klogoff',185        ; F5
  127.         mkeyw   '\Klogon',183        ; F8
  128.         mkeyw   '\Kexit',184        ; F9
  129.         mkeyw   '\Khangup',186        ; F10
  130.         dw      0               ; end of table marker
  131.  
  132. datas   ends
  133.  
  134. code    segment public 'code'
  135.                 ; system independent external items
  136.         extrn   comnd:near, prompt:near                 ; in msscmd
  137.         extrn   strlen:near                             ; in mssfil
  138.         extrn   cnvlin:near, katoi:near, decout:near    ; in msster
  139.                 ; system dependent external items
  140.                 ; these are system dependent action verbs, in msxgen
  141.         extrn   beep:near, trnprs:near, sendbr:near
  142.         extrn   chrout:near, cstatus:near, cquit:near, cquery:near
  143.         extrn   klogon:near, klogof:near, kdos:near, snull:near, chang:near
  144.  
  145.         assume  cs:code, ds:datas, es:datas
  146.  
  147. ; Begin system independent Keyboard Translator code
  148.  
  149. ; MSUINIT performs Kermit startup initialization for this file.
  150. ; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
  151. ; are not initialized here then the older Set/Show Key procedures are called.
  152. MSUINIT PROC    NEAR                    ; call from msx/msy init code
  153.         call    kbdinit                 ; optional: init translator tables
  154.         mov     shkadr,offset shkey     ; declare keyboard translator present
  155.         mov     stkadr,offset dfkey     ; via Show and Set Key proc addresses
  156.         ret
  157. MSUINIT ENDP
  158.  
  159. ; Call Keybd to read a keyboard char (just returns carry clear if none) and
  160. ; 1) send the replacement string (or original char if not translated)
  161. ;    out the serial port, or
  162. ; 2) execute a Kermit action verb.
  163. ; Returns carry set if Connect mode is to be exited, else carry clear.
  164. ; Modifies registers ax and bx.
  165. KEYBD   PROC    NEAR                    ; active translator
  166.         call    getkey                  ; read keyboard
  167.         jnc     keybd1                  ; nc = data available
  168.         jmp     keybdx                  ; else just return carry clear
  169. keybd1: call    postkey                 ; call system dependent post processor
  170.         cmp     nkeys,0                 ; is number of keys defined = 0?
  171.         jz      keybd3                  ; z = none defined
  172.         push    di                      ; search keylist for this keycode
  173.         push    cx                      ; save some registers
  174.         push    es
  175.         mov     di,offset keylist       ; list of defined keycode words
  176.         mov     ax,keycode              ; present keycode
  177.         mov     cx,nkeys                ; number of words to examine
  178.         push    ds
  179.         pop     es                      ; make es:di point to datas segment
  180.         cld
  181.         repne   scasw                   ; find keycode in list
  182.         pop     es                      ; restore regs
  183.         pop     cx
  184.         je      keybd1b                 ; e = found, work with present di
  185.         pop     di                      ; restore original di
  186.         test    keycode,scan            ; is this a scan code?
  187.         jz      keybd3                  ; z = no, it's ascii, use al as char
  188.         call    beep                    ; say key is a dead one
  189.         clc
  190.         ret                             ; and exit with no action
  191.  
  192. keybd1b:sub     di,2                    ; correct for auto increment
  193.         sub     di,offset keylist       ; subtract start of list ==> listptr
  194.         mov     ax,dirlist[di]          ; ax = contents of director word
  195.         pop     di                      ; restore original di
  196.                                         ; dispatch on Director code
  197.         test    ax,verb                 ; verb only?
  198.         jnz     keyvb                   ; e = yes
  199.         test    ax,strng                ; multi-char string only?
  200.         jnz     keyst                   ; e = yes, else single char & no xlat.
  201.                                         ;
  202.                                         ; do single CHAR output (char in al)
  203. keybd3: cmp     al,trans.escchr         ; Kermit's escape char?
  204.         je      keybd3a                 ; e = yes, handle separately
  205.         call    chrout                  ; transmit the char
  206.         clc                             ; return success
  207.         ret
  208. keybd3a:stc                             ; set carry for jump to Quit
  209.         ret
  210.  
  211. keyvb:  and     ax,not(verb+strng)      ; VERB (ax=index, remove type bits)
  212.         mov     bx,offset kverbs        ; start of verb table
  213.         cmp     al,byte ptr [bx]        ; index > number of entries?
  214.         jae     keybdx                  ; ae = illegal, indices start at 0
  215.         inc     bx                      ; bx points to first entry
  216.         push    cx                      ; save reg
  217.         mov     cx,ax                   ; save the index in cx
  218.         inc     cx                      ; counter, indices start at 0
  219. keyvb1: mov     al,byte ptr [bx]        ; cnt value
  220.         xor     ah,ah
  221.         add     ax,4                    ; skip text and '?' and value word
  222.         add     bx,ax                   ; look at next slot
  223.         loop    keyvb1                  ; walk to correct slot
  224.         sub     bx,2                    ; backup to value field
  225. keyvb2: pop     cx                      ; restore reg
  226.         mov     bx,[bx]                 ; get value field of this slot
  227.         cmp     bx,0                    ; jump address defined?
  228.         je      keybdx                  ; e = no, skip the action
  229.         jmp     bx                      ; perform the function
  230.  
  231. keyst:  and     ax,not(verb+strng)      ; STRING (ax=index, remove type bits)
  232.         shl     ax,1                    ; convert to word index
  233.         push    si                      ; save working reg
  234.         mov     si,ax                   ; word subscript in table
  235.         mov     si,sptable[si]          ; memory offset of selected string
  236.         cmp     si,0                    ; is there a string pointer present?
  237.         je      keyst3                  ; e = no, skip operation
  238.         cld                             ; scan forward
  239.         lodsb                           ; get string length byte
  240.         mov     cl,al
  241.         xor     ch,ch                   ; to cx for looping
  242.         jcxz    keybdx                  ; z = null length
  243. keyst2: lodsb                           ; get new string char into al
  244.         push    si                      ; save si and cx around call
  245.         push    cx
  246.         call    chrout                  ; send out the char in al
  247.         pop     cx                      ; recover regs
  248.         pop     si
  249.         loop    keyst2                  ; loop through whole string
  250. keyst3: pop     si                      ; restore reg
  251.  
  252. keybdx: clc                             ; return success
  253.         ret
  254. KEYBD   ENDP
  255.  
  256. ; SET KEY - define a key   (procedure dfkey)
  257. ; SET KEY <key ident><whitespace><new meaning>
  258. ; Call from Kermit level. Returns as ret if failure or as rskp if success.
  259. ;
  260. DFKEY   PROC    NEAR                    ; define a key as a verb or a string
  261.         mov     keycode,0               ; clear keycode
  262.         mov     oldform,0               ; say no old form Set Key yet
  263.         mov     dx,offset tranbuf       ; our work space
  264.         mov     word ptr tranbuf,0      ; insert terminator
  265.         mov     bx,offset dfhelp1       ; first help message
  266.         mov     ah,cmfile               ; parse a word
  267.         call    comnd                   ; get key code or original ascii char
  268.          nop
  269.          nop
  270.          nop
  271.         mov     al,intake               ; reading from Take file indirectly
  272.         or      al,taklev               ; ditto, directly
  273.         mov     msutake,al              ; save here
  274.         or      ah,ah                   ; any text given?
  275.         jnz     dfkey12                 ; nz = yes, so don't consider prompts
  276.                                         ; interactive key request
  277.         cmp     intake,0                ; in a Take file?
  278.         je      dfkey10                 ; e = no, prompt for keystroke
  279.         jmp     dfkey0                  ;  else say bad syntax
  280. dfkey10:mov     ah,prstr
  281.         mov     dx,offset dfaskky       ; ask for key to be pressed
  282.         int     dos
  283. dfkey11:call    getkey                  ; read key ident from keyboard
  284.         jc      dfkey11                 ; c = no response, wait for keystroke
  285.         mov     ah,prstr                ; display cr/lf
  286.         mov     dx,offset crlf
  287.         int     dos
  288.         call    shkey0                  ; show current definition (in SHKEY)
  289.         jmp     dfkey1e                 ; prompt for and process definition
  290.  
  291. dfkey12:                                ; Look for word SCAN and ignore it
  292.         mov     dx,word ptr tranbuf     ; get first two characters
  293.         or      dx,2020h                ; map upper to lower case
  294.         cmp     dx,'cs'                 ; first two letters of word "scan"?
  295.         je      dfkey                   ; e = yes, skip the word
  296.         cmp     dx,'lc'                 ; first two letters of word "clear"?
  297.         je      dfkeyc                  ; e = yes, reinit keyboard
  298.         cmp     ah,1                    ; number of characters received
  299.         ja      dfkey1                  ; a = more than one, decode
  300.         mov     ah,byte ptr tranbuf     ; get the single char
  301.         mov     byte ptr keycode,ah     ; store as ascii keycode
  302.         jmp     dfkey1b                 ; go get definition
  303.  
  304. dfkey0: mov     dx,offset dfhelp1       ; say bad definition command
  305.         mov     ah,prstr
  306.         int     dos
  307.         jmp     rskp
  308.  
  309. dfkeyc:                                 ; CLEAR key defs, restore startup defs
  310.         mov     cx,maxkeys              ; size of keycode tables
  311.         push    es                      ; save register
  312.         push    ds
  313.         pop     es                      ; make es point to datas segment
  314.         mov     ax,0                    ; null, value to be stored
  315.         mov     di,offset dirlist       ; director table
  316.         cld
  317.         rep     stosw                   ; clear it
  318.         mov     cx,maxkeys
  319.         mov     di,offset keylist       ; keycode table
  320.         rep     stosw                   ; clear it
  321.         mov     cx,maxstng
  322.         mov     di,offset sptable       ; string pointer table
  323.         rep     stosw                   ; clear it
  324.         pop     es                      ; recover register
  325.         mov     strmax,offset stbuf     ; clear string buffer
  326.         mov     stbuf,0                 ;
  327.         mov     nkeys,0                 ; clear number of defined keys
  328.         call    msuinit                 ; restore startup definitions
  329.         jmp     rskp
  330.                                         ; Multi-char key identification
  331. dfkey1: mov     si,offset tranbuf       ; point to key ident text
  332.         cmp     byte ptr [si],'0'       ; is first character numeric?
  333.         jb      dfkey1a                 ; b = no
  334.         cmp     byte ptr [si],'9'       ; in numbers?
  335.         ja      dfkey1a                 ; a = no
  336.         mov     keycode,scan            ; setup keycode for scan value
  337.         mov     dx,si                   ; get length of string in cx
  338.         call    strlen
  339.         push    ds
  340.         pop     es                      ; make es point to datas segment
  341.         push    si
  342.         add     si,cx                   ; point at string terminator
  343.         mov     di,si
  344.         inc     di                      ; place to store string (1 byte later)
  345.         inc     cx                      ; include null terminator
  346.         std                             ; work backward
  347.         rep     movsb                   ; move string one place later
  348.         cld
  349.         pop     si
  350.         mov     byte ptr [si],'\'       ; make ascii digits into \nnn form
  351.         mov     oldform,0ffh            ; set old form flag
  352.         mov     dx,offset kwarnmsg      ; tell user this is old form
  353.         mov     ah,prstr
  354.         int     dos
  355. dfkey1a:call    katoi                   ; convert ascii number to binary in ax
  356.         jc      dfkey0                  ; c = no number converted
  357.         or      keycode,ax              ; store in keycode
  358.  
  359. dfkey1b:                                ; Get Definition proper
  360.         test    oldform,0ffh            ; old form Set Key active?
  361.         jz      dfkey1f                 ; z = no
  362.         mov     bx,offset tranbuf       ; get new definition on main cmd line
  363.         mov     word ptr [bx],0         ; insert terminator
  364.         mov     dx,offset dfhelp2       ; help for definition of key
  365.         mov     ah,cmtxt                ; read rest of line into tranbuf
  366.         call    comnd
  367.          nop                            ; allow null definitions
  368.          nop
  369.          nop
  370.         or      ah,ah                   ; char count zero?
  371.         jz      dfkey1e                 ; z = zero, prompt for definition
  372.         jmp     dfkey1g                 ; process definition
  373.  
  374. dfkey1e:mov     ah,prstr
  375.         mov     dx,offset crlf
  376.         int     dos
  377.         mov     dx,offset dfaskdf       ; prompt for definition string
  378.         call    prompt                  ; Kermit prompt routine
  379.         mov     comand.cmcr,1           ; permit bare carriage returns
  380. dfkey1f:mov     bx,offset tranbuf       ; get new definition
  381.         mov     word ptr [bx],0         ; insert terminator
  382.         mov     dx,offset dfhelp2       ; help for definition of key
  383.         mov     ah,cmtxt                ; read rest of line into tranbuf
  384.         call    comnd
  385.          jmp r                          ; exit now on ^C from user
  386.          nop
  387.         cmp     comand.cmcr,0           ; prompting for definition?
  388.         je      dfkey1g                 ; e = no, trim leading whitespace
  389.         mov     comand.cmcr,0           ; turn off allowance for bare c/r's
  390.         jmp     dfkey2                  ; interactive, allow leading whitespace
  391. dfkey1g:xchg    ah,al                   ; put byte count in al
  392.         xor     ah,ah                   ; clear high byte
  393.         mov     kbtemp,ax               ; and save count in kbtemp
  394.         mov     ah,cmcfm                ; get a confirm
  395.         call    comnd
  396.          jmp    r                       ; none so declare parse error
  397.          nop                            ; round out to three bytes
  398.         mov     cx,kbtemp               ; string length
  399.         jcxz    dfkey2                  ; z = empty string
  400.         push    si
  401.         push    di
  402.         mov     si,offset tranbuf       ; strip leading white space
  403. dfkey1c:cld                             ; work forward
  404.         lodsb                           ; read string char into al
  405.         dec     cx                      ; number of chars left to read
  406.         cmp     al,' '                  ; a space?
  407.         je      dfkey1c                 ; e = yes, keep going
  408.         cmp     al,tab                  ; tab?
  409.         je      dfkey1c                 ; e = yes, keep going
  410.         dec     si                      ; offset inc si in lodsb
  411.         add     cx,2                    ; include terminator, offset dec above
  412.         jcxz    dfkey1d                 ; z = nothing to move
  413.         mov     di,offset tranbuf       ; destination is start of buffer
  414.         push    ds
  415.         pop     es
  416.         cld
  417.         rep     movsb                   ; copy text part of string
  418. dfkey1d:pop     di
  419.         pop     si
  420.  
  421. dfkey2:                                 ; Examine translation
  422.         mov     al,trans.escchr         ; current escape char (port dependent)
  423.         cmp     al,byte ptr keycode     ; is this Kermit's escape char?
  424.         jne     dfkey2a                 ; ne = no
  425.         test    keycode,scan            ; see if scan code
  426.         jnz     dfkey2a                 ; nz = scan, so not ascii esc char
  427.         mov     dx,offset dfkopps       ; Opps! msg
  428.         mov     ah,prstr                ; complain and don't redefine
  429.         int     dos
  430.         jmp     rskp
  431.  
  432. dfkey2a:push    di                      ; get a director code for this key
  433.         push    cx
  434.         mov     di,offset keylist       ; list of keycodes
  435.         mov     cx,nkeys                ; number currently defined
  436.         mov     ax,keycode              ; present keycode
  437.         jcxz    dfkey2b                 ; cx = 0 means none defined yet
  438.         cld
  439.         push    ds
  440.         pop     es
  441.         repne   scasw                   ; is current keycode in the list?
  442.         jne     dfkey2b                 ; ne = not in list
  443.         sub     di,2                    ; correct for auto increment
  444.         sub     di,offset keylist
  445.         mov     listptr,di              ; list pointer for existing definition
  446.         pop     cx
  447.         pop     di
  448.         jmp     dfkey3                  ; go process definition
  449.  
  450. dfkey2b:pop     cx                      ; key not currently defined so
  451.         pop     di                      ;  make a new director entry for it
  452.         mov     bx,nkeys                ; number of keys previously defined
  453.         cmp     bx,maxkeys              ; enough space?
  454.         jae     dfkey2c                 ; ae = no, complain
  455.         shl     bx,1                    ; count words
  456.         mov     listptr,bx              ; index into word list
  457.         mov     ax,keycode              ; get key's code
  458.         mov     keylist[bx],ax          ; store it in list of keycodes
  459.         mov     dirlist[bx],0           ; clear the new director entry
  460.         inc     nkeys                   ; new number of keys
  461.         jmp     dfkey3                  ; go process definition
  462.  
  463. dfkey2c:mov     dx,offset keyfull       ; say key space is full already
  464.         mov     ah,prstr
  465.         int     dos
  466.         jmp     rskp                    ; tell parser we are happy
  467. ; listptr has element number in keylist or dirlist; keycode has key's code.
  468.  
  469. ; Parse new definition. First look for Kermit verbs as a line beginning
  470. ; as \K or \{K. Otherwise, consider the line to be a string.
  471. ; In any case, update the Director table for the new definition.
  472.  
  473. dfkey3: mov     brace,0                 ; assume not using braces
  474.         mov     si,offset tranbuf       ; start of definition text
  475.         cmp     byte ptr [si],'\'       ; starts with escape char?
  476.         jne     dfkey5                  ; ne = no, so we have a string
  477.         inc     si                      ; skip the backslash
  478.         cmp     byte ptr [si],braceop   ; starts with \{?
  479.         jne     dfkey3a                 ; ne = no
  480.         inc     si                      ; skip the opening brace
  481.         mov     brace,bracecl           ; expect closing brace
  482. dfkey3a:cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  483.         je      dfkey3b                 ; e = yes
  484.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  485.         jne     dfkey5                  ; ne = no, then it's a string
  486. dfkey3b:inc     si                      ; yes, skip the K too
  487.                                         ; Kermit action VERBS
  488.         push    si                      ; save verb name start address
  489. dfkey4a:cld
  490.         lodsb                           ; scan til closing brace or w/s or end
  491.         cmp     al,0                    ; premature end?
  492.         je      dfkey4b                 ; e = yes, accept without brace
  493.         cmp     al,brace                ; closing brace?
  494.         je      dfkey4b                 ; e = yes
  495.         cmp     al,spc                  ; white space or control char?
  496.         ja      short dfkey4a           ; a = no, so not at end yet
  497. dfkey4b:mov     byte ptr[si-1],0        ; insert null terminator
  498.         pop     si                      ; recover start address
  499.         call    tstkeyw                 ; find keyword, kw # returned in kbtemp
  500.         jc      dfkey4d                 ; c = no keyword found, complain
  501.         call    remstr                  ; clear old string, if string
  502.         mov     ax,kbtemp               ; save keyword number
  503.         and     ax,not(verb+strng)      ; clear verb / string field
  504.         or      ax,verb                 ; set verb ident
  505.         mov     si,listptr
  506.         mov     dirlist[si],ax          ; store info in Director table
  507.         jmp     dfkey7                  ; show results and return success
  508.  
  509. dfkey4d:mov     dx,offset verbbad       ; say no such verb
  510.         mov     ah,prstr
  511.         int     dos
  512.         jmp     rskp
  513.  
  514. ; Here we are left with the definition string; si points to its start, and
  515. ; kbtemp holds its length (number of bytes). Null termination. If the string
  516. ; begins with an opening brace it terminates on a matching closing brace
  517. ; or the end of line, whichever occurs first. Trailing whitespace removed
  518. ; before examining braces.
  519. ; Null length strings mean define key as Self.
  520.                                         ; STRING definitions
  521. dfkey5: call    remstr                  ; first, clear old string, if any
  522.         mov     si,offset tranbuf       ; si=source, di=dest, convert in-place
  523.         mov     di,si
  524.         call    cnvlin                  ; convert numbers, cx gets line length
  525.         mov     si,offset tranbuf       ; provide address of new string
  526.         cmp     cx,1                    ; just zero or one byte to do?
  527.         jbe     dfkey6                  ; e = yes, do as a char
  528.         call    insertst                ; insert new string, returns reg cx.
  529.         jc      dfkey5h                 ; c = could not do insert
  530.         mov     si,listptr              ; cx has type and string number
  531.         mov     dirlist[si],cx          ; update Director table from insertst
  532.         jmp     dfkey7                  ; show results and return success
  533.  
  534. dfkey5h:mov     dx,offset strbad        ; display complaint
  535.         mov     ah,prstr
  536.         int     dos
  537. dfkeyx: jmp     rskp
  538.  
  539.                 ; define SINGLE CHAR replacement or CLEAR a key definition.
  540.                 ; cx has char count 1 (normal) or 0 (to undefine the key).
  541. dfkey6: jcxz    dfkey6c                 ; z = cx= 0, clear definition
  542.         mov     al,byte ptr [si]        ; get first byte from definition
  543.         xor     ah,ah                   ; set the type bits to Char
  544.         mov     si,listptr
  545.         mov     dirlist[si],ax          ; store type and key's new code
  546.         jmp     dfkey7                  ; return success
  547.  
  548. dfkey6c:push    si                      ; clear a definition,
  549.         push    di                      ; listptr points to current def
  550.         mov     si,listptr              ; starting address to clear
  551.         add     si,offset dirlist
  552.         mov     di,si                   ; destination
  553.         add     si,2                    ; source is next word
  554.         mov     cx,nkeys                ; current number of keys defined
  555.         add     cx,cx                   ; double for listptr being words
  556.         sub     cx,listptr              ; cx = number of words to move
  557.         shr     cx,1                    ; convert to actual number of moves
  558.         jcxz    dfkey6d                 ; z = none, just remove last word
  559.         push    es
  560.         push    ds
  561.         pop     es                      ; make es:di point to datas segment
  562.         cld
  563.         push    cx                      ; save cx
  564.         rep     movsw                   ; move down higher list items
  565.         pop     cx
  566.         mov     si,listptr              ; do keylist too, same way
  567.         add     si,offset keylist
  568.         mov     di,si
  569.         add     si,2
  570.         rep     movsw
  571.         pop     es
  572. dfkey6d:mov     si,nkeys                ; clear old highest list element
  573.         shl     si,1                    ; address words
  574.         mov     dirlist[si],0           ; null the element
  575.         mov     keylist[si],0           ; null the element
  576.         dec     nkeys                   ; say one less key defined now
  577.         pop     di                      ; restore saved registers
  578.         pop     si
  579.  
  580. dfkey7: mov     ah,msutake              ; Finish up. In a Take file?
  581.         or      ah,taklev               ; or even directly
  582.         cmp     ah,0
  583.         je      dfkey7a                 ; e = no
  584.         cmp     flags.takflg,0          ; echo Take commands?
  585.         je      dfkey7b                 ; e = no
  586. dfkey7a:mov     ah,prstr                ; display cr/lf
  587.         mov     dx,offset crlf
  588.         int     dos
  589.         call    shkey0                  ; show new definition (in SHKEY)
  590.         call    shkfre                  ; show free string space
  591. dfkey7b:jmp     rskp                    ; return success
  592. DFKEY   ENDP
  593.  
  594. ; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
  595. ; command. Replaces obsolete procedure in msx---.
  596. ; Prompts for a key and shows that key's (or all if ? entered) keycode,
  597. ; definition, and the key definition free space remaining.
  598.  
  599. SHKEY   PROC    NEAR                    ; Show key's definition command
  600.         mov     ah,cmcfm                ; get a confirm
  601.         call    comnd
  602.          nop                            ; ignore any additional text
  603.          nop
  604.          nop
  605.         push    bx
  606.         mov     dx,offset shkmsg1       ; ask for original key
  607.         mov     ah,prstr
  608.         int     dos
  609. shky0:  call    getkey                  ; read keyboard, output to keycode
  610.         jc      shky0                   ; wait for a key (c = nothing there)
  611.         cmp     byte ptr keycode,'?'    ; query for all keys?
  612.         jne     shky0a                  ; ne = no, not a query
  613.         test    keycode,scan            ; is this a scan code, vs ascii query?
  614.         jz      shky0c                  ; z = no Scan, so it is a query
  615.  
  616. shky0a: mov     ah,prstr                ; show single key. Setup display
  617.         mov     dx,offset crlf
  618.         int     dos
  619.         call    shkey0                  ; show just one key
  620. shky0b: call    shkfre                  ; show free string space
  621.         jmp     shkeyx                  ; exit
  622.  
  623. shky0c: mov     cx,nkeys                ; Show all keys. nkeys = number defined
  624.         jcxz    shky0b                  ; z = none to show
  625.         mov     si,offset keylist       ; list of definitions
  626.         push    si                      ; save pointer
  627. shky1:  pop     si                      ; recover pointer
  628.         cld
  629.         lodsw                           ; get a keycode
  630.         push    si                      ; save pointer
  631.         push    cx                      ; save counter
  632.         mov     keycode,ax              ; save new keycode
  633.         mov     ah,prstr
  634.         mov     dx,offset crlf
  635.         int     dos
  636.         call    shkey0                  ; show this keycode
  637.  
  638.         pop     cx                      ; pause between screens, recover cntr
  639.         push    cx                      ; save it again
  640.         dec     cx                      ; number yet to be shown
  641.         jcxz    shky1b                  ; z = have now shown all of them
  642.         mov     ax,nkeys                ; number of defined keys
  643.         sub     ax,cx                   ; minus number yet to be displayed
  644.         xor     dx,dx                   ; clear extended numerator
  645.         div     twelve                  ; two lines per definition display
  646.         or      dx,dx                   ; remainder zero (12 defs shown)?
  647.         jnz     shky1b                  ; nz = no, not yet so keep going
  648.         mov     ah,prstr
  649.         mov     dx,offset shkmsg3       ; "push any key to continue" msg
  650.         int     dos
  651. shky1a: call    getkey                  ; get any key
  652.         jc      shky1a                  ; c = nothing at keyboard yet, wait
  653. shky1b: pop     cx                      ; resume loop
  654.         loop    shky1
  655.         pop     si                      ; clean stack
  656.         call    shkfre                  ; show free string space
  657.         jmp     shkeyx                  ; exit
  658.  
  659.                 ; show key worker routine, called from above
  660.                                         ; SHKEY0 called by DFKEY just above
  661. SHKEY0: test    keycode,scan            ; scan code?
  662.         jz      shkey1                  ; z = no, regular ascii
  663.  
  664.                                         ; SCAN codes
  665.         mov     dx,offset scanmsg       ; say Scan Code:
  666.         mov     ah,prstr
  667.         int     dos
  668.         mov     ah,conout
  669.         mov     dl,'\'                  ; add backslash before number
  670.         int     dos
  671.         mov     ax,keycode              ; get key's code again
  672.         call    decout                  ; display 16 bit decimal keycode
  673.         jmp     shkey2                  ; go get definition
  674.  
  675. shkey1: mov     dx,offset ascmsg        ; say ASCII CHAR
  676.         mov     ah,prstr
  677.         int     dos
  678.         mov     dl,byte ptr keycode     ; get ascii code (al part of input)
  679.         mov     ah,conout
  680.         cmp     dl,spc                  ; control code?
  681.         jae     shkey1a                 ; ae = no
  682.         push    dx                      ; save char
  683.         mov     dl,5eh                  ; show caret first
  684.         int     dos
  685.         pop     dx
  686.         add     dl,'A'-1                ; ascii bias
  687. shkey1a:cmp     dl,del                  ; DEL?
  688.         jne     shkey1b                 ; ne = no
  689.         mov     dl,'D'                  ; spell out DEL
  690.         int     dos
  691.         mov     dl,'E'
  692.         int     dos
  693.         mov     dl,'L'
  694. shkey1b:int     dos
  695.         mov     dl,spc                  ; add a couple of spaces
  696.         int     dos
  697.         int     dos
  698.         mov     dl,'\'                  ; add backslash before number
  699.         int     dos
  700.         mov     ax,keycode              ; show 16 bit keycode in decimal
  701.         call    decout                  ; and go get definiton
  702.  
  703.                                         ; Display defintion
  704. shkey2: mov     dx,offset shkmsg2       ; intermediate part of reply
  705.         mov     ah,prstr                ; " is defined as "
  706.         int     dos
  707.         push    di                      ; get a director code for this key
  708.         push    cx
  709.         mov     di,offset keylist       ; list of keycodes
  710.         mov     cx,nkeys                ; number currently defined
  711.         jcxz    shkey2a                 ; z = none
  712.         mov     ax,keycode              ; present keycode
  713.         push    ds
  714.  
  715.         pop     es                      ; use datas segment for es:di
  716.         cld
  717.         repne   scasw                   ; is current keycode in the list?
  718.         jne     shkey2a                 ; ne = not in list
  719.         sub     di,2                    ; correct for auto increment
  720.         sub     di,offset keylist
  721.         mov     listptr,di              ; list pointer for existing definition
  722.         pop     cx
  723.         pop     di
  724.         jmp     shkey3                  ; go process definition
  725.  
  726. shkey2a:pop     cx
  727.         pop     di
  728.         mov     dx,offset noxmsg        ; say Self (no translation)
  729.         mov     ah,prstr
  730.         int     dos
  731.         ret                             ; return to main show key loop
  732.  
  733. shkey3:                                 ; translations, get kind of.
  734.         mov     si,listptr
  735.         test    dirlist[si],verb        ; defined as verb?
  736.         jnz     shkey6                  ; nz = yes, go do that one
  737.         test    dirlist[si],strng       ; defined as string?
  738.         jz      shkey3a                 ; z = no
  739.         jmp     shkey8                  ; yes, do string display
  740. shkey3a:
  741.         mov     dx,offset ascmsg        ; CHAR. say 'Ascii char:'
  742.         mov     ah,prstr
  743.         int     dos
  744.         mov     ax,dirlist [si]         ; get type and char
  745.         mov     dl,al                   ; put char here for display
  746.         push    ax                      ; save here too
  747.         mov     ah,conout
  748.         cmp     dl,spc                  ; control code?
  749.         jae     shkey4                  ; ae = no
  750.         push    dx
  751.         mov     dl,5eh                  ; show caret
  752.         int     dos
  753.         pop     dx
  754.         add     dl,'A'-1                ; add ascii bias
  755. shkey4: cmp     dl,del                  ; DEL?
  756.         jne     shkey4a                 ; ne = no
  757.         mov     dl,'D'                  ; spell out DEL
  758.         int     dos
  759.         mov     dl,'E'
  760.         int     dos
  761.         mov     dl,'L'
  762. shkey4a:int     dos
  763.         mov     dl,spc                  ; add a couple of spaces
  764.         mov     ah,conout
  765.         int     dos
  766.         int     dos
  767.         mov     dl,'\'                  ; add backslash before number
  768.         int     dos
  769.         pop     ax                      ; recover char
  770.         xor     ah,ah                   ; clear high byte
  771.         call    decout                  ; show decimal value
  772.         ret                             ; return to main show key loop
  773.  
  774. shkey6: mov     ah,prstr                ; VERB
  775.         mov     dx,offset verbmsg       ; say 'verb'
  776.         int     dos
  777.         mov     si,listptr              ; get verb index from director
  778.         mov     dx,dirlist[si]
  779.         and     dx,not(verb+strng)      ; remove type bits, leaves verb number
  780.         mov     bx,offset kverbs        ; table of verbs & actions
  781.         mov     al,byte ptr [bx]        ; number of keywords
  782.         xor     ah,ah
  783.         dec     ax
  784.         mov     kwcnt,ax                ; save number of last one here
  785.         cmp     dx,ax                   ; asking for more than we have?
  786.         ja      shkeyx                  ; a = yes, exit bad
  787.         inc     bx                      ; point to first slot
  788.         mov     cx,0                    ; current slot number
  789. shkey6b:cmp     cx,dx                   ; this slot?
  790.         je      shkey6c                 ; e = yes, print the text part
  791.         ja      shkeyx                  ; a = beyond, exit bad
  792.         mov     al,byte ptr [bx]        ; get cnt (keyword length)
  793.         xor     ah,ah
  794.         add     ax,4                    ; skip over '$' and two byte value
  795.         add     bx,ax                   ; bx = start of next keyword slot
  796.         inc     cx                      ; current keyword number
  797.         jmp     short shkey6b           ; try another
  798. shkey6c:inc     bx                      ; look at text field
  799.         mov     dx,bx                   ; offset for printing
  800.         mov     ah,prstr
  801.         int     dos
  802.         mov     ah,conout
  803.         mov     dl,spc                  ; add a couple of spaces
  804.         int     dos
  805.         int     dos
  806.         mov     dl,'\'                  ; show verb name as \Kverb
  807.         int     dos
  808.         mov     dl,'K'
  809.         int     dos
  810.         mov     ah,prstr
  811.         mov     dx,bx                   ; show name part again
  812.         int     dos
  813.         ret                             ; return to main show key loop
  814.  
  815. shkey8: mov     ah,prstr                ; STRING
  816.         mov     dx,offset strngmsg      ; say String:
  817.         int     dos
  818.         mov     si,listptr              ; get index from director
  819.         mov     bx,dirlist[si]
  820.         and     bx,not(verb+strng)      ; remove type bits
  821.         shl     bx,1                    ; index words
  822.         mov     si,sptable[bx]          ; table of string offsets
  823.         mov     cl,byte ptr [si]        ; get string length byte
  824.         xor     ch,ch
  825.         inc     si                      ; point to string text
  826.         mov     ah,conout
  827. shkey8a:cld
  828.         lodsb                           ; get a byte
  829.         cmp     al,spc                  ; control code?
  830.         jae     shkey8b                 ; ae = no
  831.         push    ax
  832.         mov     dl,5eh                  ; show caret first
  833.         int     dos
  834.         pop     ax
  835.         add     al,40h                  ; convert to printable for display
  836. shkey8b:mov     dl,al
  837.         int     dos                     ; display it
  838.         loop    shkey8a                 ; do another
  839.         ret                             ; return to main show key loop
  840.  
  841. shkeyx: pop     bx                      ; restore reg
  842.         jmp     rskp                    ; return success
  843. SHKEY   ENDP
  844.  
  845. ;;;     keyboard translator local support procedures, system independent
  846.  
  847. ; Tstkeyw checks text word pointed to by si against table of keywords (pointed
  848. ; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
  849. ; Returns in kbtemp the number of the keyword and carry clear, or if failure
  850. ; returns kbtemp zero and carry set.
  851. ; Keyword structure is:         db      cnt     (length of string 'word')
  852. ;                               db      'word'  (keyword string)
  853. ;                               db      '$'     (printing terminator)
  854. ;                               dw      value   (value returned in bx)
  855. ; Make these with macro mkeyw such as   mkeyw 'test',15   with the list of
  856. ; such keywords headed by a byte giving the number of keywords in the list.
  857. tstkeyw proc    near
  858.         push    ax
  859.         push    cx
  860.         push    si
  861.         mov     verblen,0               ; verblen will hold verb length
  862.         push    si                      ; save user's verb pointer
  863. tstkw1: cld
  864.         lodsb                           ; get a verb character
  865.         cmp     al,spc                  ; verbs are all non-spaces and above
  866.         jbe     tstkw2                  ; be = done (space or control char)
  867.         inc     verblen                 ; count verb length
  868.         jmp     short tstkw1            ; printable char, look for more
  869. tstkw2: pop     si                      ; pointer to verb
  870.         mov     bx,offset kverbs        ; table of Kermit verb keywords
  871.         mov     al,byte ptr [bx]        ; number of keywords
  872.         xor     ah,ah
  873.         mov     kwcnt,ax                ; save number of keywords here
  874.         inc     bx                      ; point bx to first slot
  875.         mov     kbtemp,0                ; remember which keyword
  876.  
  877. tstkw3:                                 ; match table keyword and text word
  878.         mov     cx,verblen              ; length of user's verb
  879.         cmp     byte ptr [bx],cl        ; compare length vs table keyword
  880.         jne     tstkw4                  ; ne = not equal lengths, try another
  881.         push    si                      ; lengths match, how about spelling?
  882.         push    bx
  883.         inc     bx                      ; point at start of keyword
  884. tstkw3a:mov     ah,byte ptr [bx]        ; keyword char
  885.         mov     al,byte ptr [si]        ; text char
  886.         cmp     ah,'A'
  887.         jb      tstkw3b                 ; b = control chars
  888.         cmp     ah,'Z'
  889.         ja      tstkw3b                 ; a = not upper case alpha
  890.         add     ah,'a'-'A'              ; convert upper case to lower case
  891. tstkw3b:cmp     al,'A'
  892.         jb      tstkw3c
  893.         cmp     al,'Z'
  894.         ja      tstkw3c
  895.         add     al,'a'-'A'              ; convert upper case to lower case
  896. tstkw3c:cmp     al,ah                   ; test characters
  897.         jne     tstkw3d                 ; ne = no match
  898.         inc     si                      ; move to next char
  899.         inc     bx
  900.         loop    tstkw3a                 ; loop through entire length
  901. tstkw3d:pop     bx
  902.         pop     si
  903.         jcxz    tstkw5                  ; z: cx = 0, exit with match;
  904.                                         ;  else select next keyword
  905. tstkw4: inc     kbtemp                  ; number of keyword to test next
  906.         mov     cx,kbtemp
  907.         cmp     cx,kwcnt                ; all done? Recall kbtemp starts at 0
  908.         jae     tstkwx                  ;ae = exhausted search, unsuccessfully
  909.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  910.         xor     ah,ah
  911.         add     ax,4                    ; skip over '$' and two byte value
  912.         add     bx,ax                   ; bx = start of next keyword slot
  913.         jmp     tstkw3                  ; do another comparison
  914.  
  915. tstkw5:                                 ; get action pointer
  916.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  917.         xor     ah,ah
  918.         add     ax,2                    ; skip over '$'
  919.         add     bx,ax                   ; now bx points to dispatch value
  920.         mov     bx,[bx]                 ; bx holds dispatch value
  921.         clc                             ; carry clear for success
  922.         jmp     short tstkwxx           ; exit
  923.         ret
  924. tstkwx: xor     bx,bx                   ; exit when no match
  925.         mov     kbtemp,bx               ; make verb number be zero too
  926.         stc                             ; carry set for failure
  927. tstkwxx:pop     si
  928.         pop     cx
  929.         pop     ax
  930.         ret
  931. tstkeyw endp
  932.  
  933. ; Insert asciiz string pointed to by si into string buffer stbuf.
  934. ; Reg cx has string length upon entry.
  935. ; Success: returns offset of first free byte (strmax) in string buffer stbuf,
  936. ; cx = type and Index of new string, and carry clear.
  937. ; Failure = carry set.
  938. insertst proc   near
  939.         push    bx
  940.         push    dx
  941.         push    si
  942.         push    di
  943.         push    kbtemp          ; save this variable too
  944.         mov     dx,cx           ; save length of incoming string in dx
  945.         mov     bx,offset sptable ; table of string offsets
  946.         mov     kbtemp,0        ; slot number
  947.         mov     cx,maxstng      ; number of entries, find an empty slot
  948. insert1:cmp     word ptr[bx],0  ; slot empty?
  949.         je      insert2         ; e = yes
  950.         inc     kbtemp          ; remember slot number
  951.         add     bx,2            ; look at next slot
  952.         loop    insert1         ; keep looking
  953.         jmp     short insert4   ; get here if no empty slots
  954. insert2:                        ; see if stbuf has sufficient space
  955.         mov     cx,dx           ; length of new string to cx
  956.         mov     di,strmax       ; offset of first free byte in stbuf
  957.         add     di,cx           ; di = address where this string would end
  958.         cmp     di,offset stbuf+stbuflen ; beyond end of buffer?
  959.  
  960.         jae     insert4         ; ae = yes, not enough room
  961.  
  962.         mov     di,strmax       ; point to first free slot in stbuf
  963.         mov     [bx],di         ; fill slot with address offset of buffer
  964.         push    es
  965.         push    ds
  966.         pop     es              ; point es:di to datas segment
  967.         cld
  968.         mov     byte ptr [di],cl ; length of text for new string
  969.         inc     di              ; move to next storage slot
  970.         rep     movsb           ; copy string text
  971.         pop     es
  972.         mov     strmax,di       ; offset of next free byte
  973.         mov     cx,kbtemp       ; return new slot number with Director Index
  974.         and     cx,not(strng+verb) ; clear type bits
  975.         or      cx,strng        ; say type is multi-char string
  976.         clc                     ; say success
  977.         jmp     short insertx   ; exit
  978. insert4:stc                     ; say no-can-do
  979. insertx:pop     kbtemp
  980.         pop     di
  981.         pop     si
  982.         pop     dx
  983.         pop     bx
  984.         ret
  985. insertst endp
  986.  
  987. ; Remove (delete) string. Enter with listptr preset for director entry.
  988. ; Acts only on existing multi-char strings; recovers freed space.
  989. ; All registers preserved.
  990. remstr  proc    near
  991.         push    si
  992.         mov     si,listptr              ; list pointer
  993.         test    dirlist[si],strng       ; multi-char string?
  994.         pop     si
  995.         jnz     remst1                  ; nz = a multi-char string
  996.         ret                             ; else do nothing
  997. remst1: push    ax
  998.         push    bx
  999.         push    cx
  1000.         push    dx
  1001.         push    si
  1002.         mov     si,listptr
  1003.         mov     ax,dirlist[si]          ; Director table entry
  1004.         and     ax,not(strng+verb) ; clear type bits, leave string's pointer
  1005.         mov     dirlist[si],0           ; clear Director table entry
  1006.         shl     ax,1                    ; index words not bytes
  1007.         mov     si,offset sptable       ; list of string offsets in stbuf
  1008.         add     si,ax                   ; plus index = current slot
  1009.         mov     bx,[si]                 ; get offset of string to be deleted
  1010.         mov     dx,bx                   ; save in dx for later
  1011.         mov     cl,byte ptr [bx]        ; get length byte
  1012.         xor     ch,ch                   ; get length of subject string
  1013.         inc     cx                      ; length byte too, cx has whole length
  1014.         sub     strmax,cx       ; count space to be freed (adj end-of-buf ptr)
  1015.         mov     word ptr [si],0 ; clear sptable of subject string address
  1016.         push    cx                      ; save length of purged string
  1017.         push    di                      ; save di
  1018.         push    si
  1019.         push    es                      ; save es
  1020.         push    ds
  1021.         pop     es              ; setup es:di to be ds:offset of string
  1022.         mov     di,dx           ; destination = start address of purged string
  1023.         mov     si,dx           ; source = start address of purged string
  1024.         add     si,cx           ;  plus string length of purged string.
  1025.         mov     cx,offset stbuf+stbuflen ; 1 + address of buffer end
  1026.         sub     cx,si                   ; 1 + number of bytes to move
  1027.         dec     cx                      ; number of bytes to move
  1028.         jcxz    remst2                  ; z = none
  1029.         cld                             ; direction is forward
  1030.         rep     movsb                   ; move down preserved strings
  1031. remst2: pop     es                      ; restore regs
  1032.         pop     di
  1033.         pop     si
  1034.         pop     ax              ; recover length of purged string (was in cx)
  1035.         mov     bx,offset sptable       ; string pointer table
  1036.         mov     cx,maxstng              ; max mumber of entries
  1037. remst4: cmp     [bx],dx         ; does this entry occur before purged string?
  1038.         jbe     remst5          ; be = before or equal, so leave it alone
  1039.         sub     [bx],ax         ; recompute address (remove old string space)
  1040. remst5: add     bx,2                    ; look at next list entry
  1041.         loop    remst4                  ; do all entries in sptable
  1042.         pop     si
  1043.         pop     dx
  1044.         pop     cx
  1045.         pop     bx
  1046.         pop     ax
  1047.         ret
  1048. remstr  endp
  1049.  
  1050. shkfre  proc    near                    ; show free key & string defs & space
  1051.         push    ax                      ; preserves all registers.
  1052.         push    bx
  1053.         push    cx
  1054.         push    dx
  1055.         push    kbtemp
  1056.         mov     dx,offset fremsg
  1057.         mov     ah,prstr
  1058.         int     dos
  1059.         mov     ax,maxkeys              ; max number of key defs
  1060.         sub     ax,nkeys                ; number currently used
  1061.         call    decout                  ; show the value
  1062.         mov     ah,prstr
  1063.         mov     dx,offset kyfrdef       ; give key defs msg
  1064.         int     dos
  1065.         mov     bx,offset sptable       ; table of string pointers
  1066.         mov     cx,maxstng              ; number of pointers
  1067.         mov     kbtemp,0                ; number free
  1068. shkfr1: cmp     word ptr [bx],0         ; slot empty?
  1069.         jne     shkfr2                  ; ne = no
  1070.         inc     kbtemp                  ; count free defs
  1071. shkfr2: add     bx,2                    ; look at next slot
  1072.         loop    shkfr1                  ; do all of them
  1073.         mov     ax,kbtemp               ; number of free defs
  1074.         call    decout                  ; display
  1075.         mov     dx,offset stfrdef       ; say free string defs
  1076.         mov     ah,prstr
  1077.         int     dos
  1078.         mov     ax,offset stbuf+stbuflen ; 1 + last byte in stbuf
  1079.         sub     ax,strmax               ; offset of last free byte in stbuf
  1080.         call    decout
  1081.         mov     dx,offset stfrspc       ; give free space part of msg
  1082.         mov     ah,prstr
  1083.         int     dos
  1084.         pop     kbtemp
  1085.         pop     dx
  1086.         pop     cx
  1087.         pop     bx
  1088.         pop     ax
  1089.         ret
  1090. shkfre  endp
  1091. ; Initialize the keyboard tables at Kermit startup time. Optional procedure.
  1092. ; Requires kbdinlst to be configured with mkeyw macro in the form
  1093. ;       mkeyw   'definition',keytype*256+keycode
  1094. ; keytype is 0 for scan codes and non-zero for ascii.
  1095. ; Returns normally.
  1096. kbdinit proc    near                    ; read keyword kbdinlst and setup
  1097.         push    ds                      ;  initial keyboard assignments.
  1098.         pop     es                      ; set es:di to datas segment
  1099.         mov     taklev,1                ; pretend that we are in Take file
  1100.         mov     si,offset kbdinlst      ; start of list of definitions
  1101. kbdini1:mov     cl,byte ptr [si]        ; cnt field (keyword length of macro)
  1102.         xor     ch,ch
  1103.         jcxz    kbdinix                 ; z = null cnt field = end of list
  1104.         inc     si                      ; look at text field
  1105.         mov     di,offset tranbuf       ; where defkey expects text
  1106.         cld
  1107.         rep     movsb                   ; copy cx chars to tranbuf
  1108.         mov     byte ptr [di],0         ; insert null terminator
  1109.         inc     si                      ; skip '$' field
  1110.         mov     ax,word ptr [si]        ; get value field
  1111.         mov     keycode,ax              ; set key ident value
  1112.         push    si
  1113.         call    dfkey2                  ; put dfkey to work
  1114.          nop
  1115.          nop
  1116.          nop
  1117.         pop     si
  1118.         add     si,2                    ; point to next entry
  1119.         jmp     kbdini1                 ; keep working
  1120. kbdinix:mov     taklev,0                ; reset Take file level
  1121.         ret
  1122. kbdinit endp
  1123. ;;;     End of System Independent Procedures
  1124.  
  1125. ;;;     Begin System Dependent Procedures
  1126.  
  1127. ; Read keyboard. System dependent.
  1128. ; Return carry set if nothing at keyboard.
  1129. ; If char present return carry clear with key's code in Keycode.
  1130. ; If key is ascii put that in the low byte of Keycode and clear bit Scan in
  1131. ; the high byte; otherwise, put the scan code in the lower byte and set bit
  1132. ; Scan in the high byte.
  1133. ; Bit Scan is set if key is not an ascii code.
  1134. ; Modifies register ax.
  1135. getkey  proc    near
  1136.         mov     keycode,0
  1137.         mov     ah,dconio               ; check console
  1138.         mov     dl,0ffh                 ; input desired
  1139.         int     dos
  1140.         jnz     getky1                  ; nz = char available
  1141.         stc                             ; carry set = nothing available
  1142.         jmp     short getkyx            ; exit on no char available
  1143. getky1: cmp     al,0                    ; scan code being returned?
  1144.         jne     getky1a                 ; ne = no
  1145.         mov     ah,dconio               ; read second byte (scan code)
  1146.         mov     dl,0ffh
  1147.         int     dos
  1148.         jz      getkyx                  ; z = nothing there
  1149.         mov     ah,al                   ; scan code goes here
  1150.         mov     al,0                    ; ascii code goes here
  1151. getky1a:
  1152.         push    di                      ; check key (ax) for aliases
  1153.         push    cx
  1154.         push    es
  1155.         mov     di,offset aliaskey      ; list of aliased keys
  1156.         mov     cx,aliaslen             ; number of entries
  1157.         jcxz    getky2                  ; z = no entries
  1158.         push    ds
  1159.         pop     es                      ; make es:di point to datas segment
  1160.         cld
  1161.         repne   scasw                   ; look for a match
  1162.         jne     getky2                  ; ne = not there
  1163.         mov     al,0                    ; force use of scan code (in ah)
  1164. getky2: pop     es
  1165.         pop     cx
  1166.         pop     di
  1167.         or      al,al                   ; scan code being returned?
  1168.         jnz     getky3                  ; nz = no
  1169.         xchg    ah,al                   ; put scan code in ident area
  1170.         or      keycode,scan            ; set scan flag (vs ascii)
  1171. getky3: mov     byte ptr keycode,al     ; return key's code (usually ascii)
  1172.         clc                             ; carry clear = got a char
  1173. getkyx: ret
  1174. getkey  endp
  1175.  
  1176.  
  1177. postkey proc    near                    ; do sys dep action after reading
  1178.         ret                             ; key during active translation
  1179. postkey endp
  1180.  
  1181. ; Jumping to this location is like retskp.  It assumes the instruction
  1182. ;   after the call is a jmp addr.
  1183.  
  1184. RSKP    PROC    NEAR
  1185.         pop bp
  1186.         add bp,3
  1187.         push bp
  1188.         ret
  1189. RSKP    ENDP
  1190.  
  1191. ; Jumping here is the same as a ret.
  1192.  
  1193. R       PROC    NEAR
  1194.         ret
  1195. R       ENDP
  1196.  
  1197. code    ends
  1198.         end
  1199.