home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccuibm.asm < prev    next >
Assembly Source File  |  2020-01-01  |  62KB  |  1,276 lines

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