home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msuz10.asm < prev    next >
Assembly Source File  |  2020-01-01  |  96KB  |  2,007 lines

  1.         NAME    msuz10
  2. ; file MSUZ10.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Kermit system dependent module for Heath/Zenith Z100
  9. ; Keyboard translator, by Joe R. Doupnik, Dec 1986
  10. ;  with contributions from David L. Knoell.
  11. ; Adapted for the Z-100 by Bo G. Gedda, May 1990
  12. ; Edit history
  13. ; 2 March 1991 version 3.10
  14. ; Last edit 20 August 1992
  15. ; Kverb \kscroll (F11) added
  16. ; Bo Gedda
  17. ;
  18. ;
  19.  
  20.         public  keybd, dfkey, shkey, msuinit, kbcodes, keycom, dosflg, dosflg1
  21.  
  22. ; some definitions
  23.  
  24. shift   equ     200h                    ; IBM, synonym for right or left shift
  25. control equ     400h                    ; IBM, synonym for control shift
  26. alt     equ     800h                    ; IBM, synonym for alt shift
  27.  
  28. maxkeys equ     200                     ; maximum number of key definitions
  29. maxstng equ     128                     ; maximum number of multi-char strings
  30. stbuflen equ    1000                    ; length of string buffer (bytes)
  31.  
  32. verb    equ     8000h                   ; dirlist flag: use verb action table
  33. strng   equ     4000h                   ; dirlist flag: use string action table
  34. scan    equ     100h                    ; keycode flag: code is scan not ascii
  35. braceop equ     7bh                     ; opening curly brace
  36. bracecl equ     7dh                     ; closing curly brace
  37.  
  38. ; Z-100 Keyboard ports
  39. keydat  equ     0f4h            ; data
  40. keycmd  equ     0f5h            ; command
  41. keystat equ     keycmd          ; status
  42.  
  43. ; Z-100 Keyboard status masks
  44. KPR     equ     2               ; 00000010b, ready if this is NOT set
  45. KDA     equ     1               ; 00000001b, data available if set
  46.  
  47. ; Z-100 Keyboard commands
  48. keyrst  equ     00h             ; reset
  49. keyrpon equ     01h             ; auto repeat on
  50. keyrpof equ     02h             ; auto repeat off
  51. keyclon equ     03h             ; click on
  52. keyclof equ     04h             ; click off
  53. keyclr  equ     05h             ; clear buffer
  54. keycli  equ     06h             ; make key click
  55. keybel  equ     07h             ; make bell sound
  56. keyena  equ     08h             ; enable keyboard
  57. keydis  equ     09h             ; disable keyboard
  58. keyeve  equ     0ah             ; make keyboard event driven (up/down mode)
  59. keyasc  equ     0bh             ; make keyboard scan ascii
  60. keyiena equ     0ch             ; enable interrupt
  61. keyidis equ     0dh             ; disable interrupt
  62.  
  63. data    segment
  64.         extrn taklev:byte, comand:byte, flags:byte
  65.         extrn shkadr:word, stkadr:word, trans:byte, ttyact:byte
  66.                                                 ; system dependent references
  67.     extrn vtmacname:word, vtmaclen:word    ; external macro, in msyibm
  68.         extrn vtemu:byte                ; emulator data
  69.         
  70. ;;;     System Independent local storage
  71.  
  72. tranbuf db      132 dup (?)             ; 132 byte translator work buffer
  73. crlf    db      cr,lf,'$'
  74. dfhelp1 db    cr,lf,' Enter key',27h,'s identification as a character',cr,lf
  75.         db      '  or as its numerical equivalent \{b##} of ascii',cr,lf
  76.         db      '  or as its scan code \{b##}'
  77.         db      cr,lf,'  or as SCAN followed by its scan code',cr,lf
  78.         db      '    where b is O for octal, X for hex, or D for decimal'
  79.         db      ' (default).',cr,lf,'    Braces {} are optional.'
  80.         db      cr,lf,'    Follow the identification with the new definition.'
  81.         db      cr,lf,' or CLEAR to restore initial key settings'
  82.         db      cr,lf,' or ON (def) to use SCAN CODES, OFF to use ASCII.$';Z100
  83. dfaskky db      cr,lf,' Push key to be defined: $'
  84. dfaskdf db      ' Enter new definition: ',0             ; asciiz for prompt
  85. verbbad db      cr,lf,' No such verb',cr,lf,'$'
  86. strbad  db      cr,lf,' Not enough space for new string',cr,lf,'$'
  87. keyfull db      cr,lf,' No more space to define keys',cr,lf,'$'
  88. dfkoops db      cr,lf,' Oops! That is Kermit',27h,'s Escape Char.'
  89.         db      ' Translation is not permitted.',cr,lf,'$'
  90. shkmsg1 db      cr,lf,'Push key to be shown (? shows all): $'
  91. shkmsg2 db      ' decimal is defined as',cr,lf,'$'
  92. shkmsg3 db      cr,lf,'... more, press a key to continue ...$'
  93. kwarnmsg db     cr,lf,' Notice: this form of Set Key is obsolete$'
  94.  
  95. ascmsg  db      ' Ascii char: $'
  96. scanmsg db      ' Scan Code $'
  97. strngmsg db     ' String: $'
  98. verbmsg db      ' Verb: $'
  99. noxmsg  db      ' Self, no translation.$'
  100. fremsg  db      cr,lf,' Free space: $'
  101. kyfrdef db      ' key and $'
  102. stfrdef db      ' string definitions, $'
  103. stfrspc db      ' string characters.',cr,lf,'$'
  104.                                         ; translation tables
  105. keylist dw      maxkeys dup (0)         ; 16 bit keycodes, paralled by dirlist
  106. dirlist dw      maxkeys dup (0)         ; director {v+s} + {index | new char}
  107. sptable dw      maxstng dup (0)         ; list of asciiz string offsets
  108. stbuf   dw      stbuflen dup (0)        ; buffer for strings
  109. strmax  dw      stbuf                   ; first free byte in stbuf
  110. listptr dw      ?                       ; item number for keylist and dirlist
  111. nkeys   dw      0                       ; number of actively defined keys
  112. keycode dw      ?                       ; ascii/scan code for key
  113. kbtemp  dw      ?                       ; scratch storage for translator
  114. brace   db      ?                       ; brace detected flag byte
  115. oldform db      0                       ; old form Set Key, if non-zero
  116. verblen dw      ?                       ; length of user's verb (work temp)
  117. kwcnt   dw      ?                       ; number of keywords (work temp)
  118. msutake db      ?                       ; if being run from take file or not
  119. stringcnt dw    0                       ; qty of string chars to be processed
  120. stringptr dw    0                       ; address of next string char
  121. twelve  dw      11d                 ; sorry, one less than that for Z-100
  122. dosflg  db      0
  123. ;;;     End System Independent Data Area
  124.  
  125. ;;;     System Dependent Data Area
  126. dosflg1 db      0               ; scan codes enabled/key extension disabled=1
  127. nrcptr  dw      0               ; pointer to code page to NRC table
  128. latinptr dw     0               ; pointer to code page to Latin1 table
  129. DECmnptr dw     0               ; pointer to code page to DEC-MCS table
  130. ;       edit dfhelp2 to include nice list of verbs for this system.
  131. dfhelp2 db      cr,lf,' Enter either  \Kverb  for a Kermit action verb',cr,lf
  132.         db      ' or a replacement string  (single byte binary numbers are'
  133.         db      ' \{b##})',cr,lf,' or push Return to undefine a key, ^C to'
  134.         db      ' retain current definition.'
  135.         db      cr,lf,' Braces {} are optional, and strings maybe enclosed in'
  136.         db      ' them.',cr,lf,' Strings may not begin with the character'
  137.         db      ' combinations of  \k  or  \{k',cr,lf
  138.         db      '    (start with a { brace instead).',cr,lf,lf
  139.         db      ' Verbs are as follows. VT52 keys (arrows and keypad):',cr,lf
  140.         db   '   uparr, dnarr, lfarr, rtarr, kpminus, kpcoma, kpdot, kpenter,'
  141.         db      cr,lf
  142.         db   '   Gold (same as PF1), PF1, PF2, PF3, PF4, kp0, ... kp9'
  143.     db      cr,lf,' Z-100/Heath-19 function and special key actions:',cr,lf
  144.     db   '   F0, ... F12, SF0, ... SF11, i_chr, d_chr, i_line, d_line'
  145.         db      cr,lf,' Kermit screen control and actions:',cr,lf
  146.         db   '   upscn, dnscn, homscn, endscn, upone, dnone, prtscn, dump,'
  147.         db      cr,lf
  148.     db   '   scroll, logoff, logon, modeline, break, lbreak,'
  149.         db      cr,lf
  150. ;        db   '   logoff, logon, termtype, reset, modeline, break,'
  151.  ;       db      ' lbreak, nethold,'
  152.   ;      db      cr,lf
  153.         db   '   hangup, null (send one), DOS, help,'
  154.         db   ' status, exit'
  155.         db      cr,lf,'$'
  156.  
  157.         ; Z-100 scan codes, used for setting keycode shift and control flags
  158.         ; column 1 unshift, column 2 shift, column 3 control, column 4
  159.         ; shift-control
  160. z10keyl equ     this byte
  161.         db      30h,29h,30h,29h         ; 0,)
  162.         db      31h,21h,31h,21h         ; 1,!
  163.         db      32h,40h,32h,00h         ; 2,@
  164.         db      33h,23h,33h,23h         ; 3,#
  165.         db      34h,24h,34h,24h         ; 4,$
  166.         db      35h,25h,35h,25h         ; 5,%
  167.         db      36h,5eh,36h,1eh         ; 6,^
  168.         db      37h,26h,37h,26h         ; 7,&
  169.         db      38h,2ah,38h,2ah         ; 8,*
  170.         db      39h,28h,39h,28h         ; 9,(
  171.         db      61h,41h,01h,01h         ; a,A
  172.         db      62h,42h,02h,02h         ; b,B
  173.         db      63h,43h,03h,03h         ; c,C
  174.         db      64h,44h,04h,04h         ; d,D
  175.         db      65h,45h,05h,05h         ; e,E
  176.         db      66h,46h,06h,06h         ; f,F
  177.         db      67h,47h,07h,07h         ; g,G
  178.         db      68h,48h,08h,08h         ; h,H
  179.         db      69h,49h,09h,09h         ; i,I
  180.         db      6ah,4ah,0ah,0ah         ; j,J
  181.         db      6bh,4bh,0bh,0bh         ; k,K
  182.         db      6ch,4ch,0ch,0ch         ; l,L
  183.         db      6dh,4dh,0dh,0dh         ; m,M
  184.         db      6eh,4eh,0eh,0eh         ; n,N
  185.         db      6fh,4fh,0fh,0fh         ; o,O
  186.         db      70h,50h,10h,10h         ; p,P
  187.         db      71h,51h,11h,11h         ; q,Q
  188.         db      72h,52h,12h,12h         ; r,R
  189.         db      73h,53h,13h,13h         ; s,S
  190.         db      74h,54h,14h,14h         ; t,T
  191.         db      75h,55h,15h,15h         ; u,U
  192.         db      76h,56h,16h,16h         ; v,V
  193.         db      77h,57h,17h,17h         ; w,W
  194.         db      78h,58h,18h,18h         ; x,X
  195.         db      79h,59h,19h,19h         ; y,Y
  196.         db      7ah,5ah,1ah,1ah         ; z,Z
  197.         db      08h,08h,08h,08h         ; BACKSPACE
  198.         db      09h,09h,09h,09h         ; TAB
  199.         db      0ah,0ah,0ah,0ah         ; LINE FEED
  200.         db      0dh,0dh,0dh,0dh         ; RETURN
  201.         db      1bh,1bh,1bh,1bh         ; ESC
  202.         db      20h,20h,20h,20h         ; SPACE
  203.         db      27h,22h,27h,22h         ; ',"
  204.         db      2ch,3ch,2ch,3ch         ; ,,<
  205.         db      2dh,5fh,2dh,1fh         ; -,_
  206.         db      2eh,3eh,2eh,3eh         ; .,>
  207.         db      2fh,3fh,2fh,3fh         ; /,?
  208.         db      3bh,3ah,3bh,3ah         ; ;,:
  209.         db      3dh,2bh,3dh,2bh         ; =,+
  210.         db      5bh,7bh,1bh,7bh         ; [,{
  211.         db      5ch,7ch,1ch,7ch         ; \,|
  212.         db      5dh,7dh,1dh,7dh         ; ],}
  213.         db      60h,7eh,60h,7eh         ; `,~
  214.         db      7fh,7fh,7fh,7fh         ; DELETE
  215.         db      8dh,0cdh,8dh,0cdh       ; ENTER
  216.         db      95h,0d5h,95h,0c5h       ; HELP
  217.         db      96h,0d6h,96h,0d6h       ; F0
  218.         db      97h,0d7h,97h,0d7h       ; F1
  219.         db      98h,0d8h,98h,0d8h       ; F2
  220.         db      99h,0d9h,99h,0d9h       ; F3
  221.         db      9ah,0dah,9ah,0dah       ; F4
  222.         db      9bh,0dbh,9bh,0dbh       ; F5
  223.         db      9ch,0dch,9ch,0dch       ; F6
  224.         db      9dh,0ddh,9dh,0ddh       ; F7
  225.         db      9eh,0deh,9eh,0deh       ; F8
  226.         db      9fh,0dfh,9fh,0dfh       ; F9
  227.         db      0a0h,0e0h,0a0h,0e0h     ; F10
  228.         db      0a1h,0e1h,0a1h,0e1h     ; F11
  229.         db      0a2h,0e2h,0a2h,0e2h     ; F12
  230.         db      0a3h,0e3h,0a3h,0e3h     ; I CHR, D CHR
  231.         db      0a4h,0e4h,0a4h,0e4h     ; I LINE, D LINE
  232.         db      0a5h,0e5h,0a5h,0e5h     ; UP ARROW
  233.         db      0a6h,0e6h,0a6h,0e6h     ; DOWN ARROW
  234.         db      0a7h,0e7h,0a7h,0e7h     ; RIGHT ARROW
  235.         db      0a8h,0e8h,0a8h,0e8h     ; LEFT ARROW
  236.         db      0a9h,0e9h,0a9h,0e9h     ; HOME
  237.         db      0aah,0eah,0aah,0eah     ; BREAK
  238.         db      0adh,0edh,0adh,0edh     ; keypad -
  239.         db      0aeh,0eeh,0aeh,0eeh     ; keypad .
  240.         db      0b0h,0f0h,0b0h,0f0h     ; keypad 0
  241.         db      0b1h,0f1h,0b1h,0f1h     ; keypad 1
  242.         db      0b2h,0f2h,0b2h,0f2h     ; keypad 2
  243.         db      0b3h,0f3h,0b3h,0f3h     ; keypad 3
  244.         db      0b4h,0f4h,0b4h,0f4h     ; keypad 4
  245.         db      0b5h,0f5h,0b5h,0f5h     ; keypad 5
  246.         db      0b6h,0f6h,0b6h,0f6h     ; keypad 6
  247.         db      0b7h,0f7h,0b7h,0f7h     ; keypad 7
  248.         db      0b8h,0f8h,0b8h,0f8h     ; keypad 8
  249.         db      0b9h,0f9h,0b9h,0f9h     ; keypad 9
  250. lz10keyl equ    $ - z10keyl
  251.  
  252. kverbs  db      72                      ; number of table entries below
  253.         mkeyw   'uparr',uparrw          ; independent of ordering and case!
  254.         mkeyw   'dnarr',dnarrw          ; mkeyw 'name',procedure entry point
  255.         mkeyw   'lfarr',lfarr
  256.         mkeyw   'rtarr',rtarr
  257.         mkeyw   'Gold',pf1
  258.         mkeyw   'PF1',pf1
  259.         mkeyw   'PF2',pf2
  260.         mkeyw   'PF3',pf3
  261.         mkeyw   'PF4',pf4
  262.         mkeyw   'KP0',kp0
  263.         mkeyw   'KP1',kp1
  264.         mkeyw   'KP2',kp2
  265.         mkeyw   'KP3',kp3
  266.         mkeyw   'KP4',kp4
  267.         mkeyw   'KP5',kp5
  268.         mkeyw   'KP6',kp6
  269.         mkeyw   'KP7',kp7
  270.         mkeyw   'KP8',kp8
  271.         mkeyw   'KP9',kp9
  272.         mkeyw   'kpminus',kpminus
  273.         mkeyw   'kpcoma',kpcoma
  274.         mkeyw   'kpenter',kpenter
  275.         mkeyw   'kpdot',kpdot
  276.         mkeyw   'F0',f0
  277.         mkeyw   'F1',f1
  278.         mkeyw   'F2',f2
  279.         mkeyw   'F3',f3
  280.         mkeyw   'F4',f4
  281.         mkeyw   'F5',f5
  282.         mkeyw   'F6',f6
  283.         mkeyw   'F7',f7
  284.         mkeyw   'F8',f8
  285.         mkeyw   'F9',f9
  286.         mkeyw   'F10',f10
  287.         mkeyw   'F11',f11
  288.         mkeyw   'F12',f12
  289.         mkeyw   'SF0',sf0
  290.         mkeyw   'SF1',sf1
  291.         mkeyw   'SF2',sf2
  292.         mkeyw   'SF3',sf3
  293.         mkeyw   'SF4',sf4
  294.         mkeyw   'SF5',sf5
  295.         mkeyw   'SF6',sf6
  296.         mkeyw   'SF7',sf7
  297.         mkeyw   'SF8',sf8
  298.         mkeyw   'SF9',sf9
  299.         mkeyw   'SF10',sf10
  300.         mkeyw   'SF11',sf11
  301.         mkeyw   'i_chr',i_chr
  302.         mkeyw   'd_chr',d_chr
  303.         mkeyw   'i_line',i_line
  304.         mkeyw   'd_line',d_line
  305. comment @
  306.         mkeyw   'decF6',decf6
  307.         mkeyw   'decF7',decf7
  308.         mkeyw   'decF8',decf8
  309.         mkeyw   'decF9',decf9
  310.         mkeyw   'decF10',decf10
  311.         mkeyw   'decF11',decf11
  312.         mkeyw   'decF12',decf12
  313.         mkeyw   'decF13',decf13
  314.         mkeyw   'decF14',decf14
  315.         mkeyw   'decHelp',dechelp
  316.         mkeyw   'decDo',decdo
  317.         mkeyw   'decF17',decf17
  318.         mkeyw   'decF18',decf18
  319.         mkeyw   'decF19',decf19
  320.         mkeyw   'decF20',decf20
  321.         mkeyw   'decFind',decfind
  322.         mkeyw   'decInsert',decinsert
  323.         mkeyw   'decRemove',decremove
  324.         mkeyw   'decSelect',decselect
  325.         mkeyw   'decPrev',decprev
  326.         mkeyw   'decNext',decnext
  327.         mkeyw   'termtype',vtans52
  328.         mkeyw   'reset',vtinit
  329. end comment @
  330.         mkeyw   'dnscn',dnwpg
  331.         mkeyw   'upscn',upwpg
  332.         mkeyw   'endscn',endwnd
  333.         mkeyw   'upone',upone
  334.         mkeyw   'dnone',dnone
  335.         mkeyw   'prtscn',trnprs
  336.         mkeyw   'dump',dmpscn
  337.         mkeyw   'homscn',homwnd
  338.         mkeyw   'modeline',trnmod
  339.         mkeyw   'break',sendbr
  340.         mkeyw   'lbreak',sendbl
  341.         mkeyw   'hangup',chang
  342.         mkeyw   'null',snull
  343.         mkeyw   'logon',klogon
  344.         mkeyw   'logoff',klogof
  345.         mkeyw   'DOS',cdos
  346.         mkeyw   'help',cquery
  347.         mkeyw   'status',cstatus
  348.         mkeyw   'exit',cquit
  349.     mkeyw    'scroll',scroll
  350.  
  351.                                         ; Kermit Z-100 Initialization keypad
  352.                                         ;  data.
  353.                                         ; PF1 to PF4 are shifted home,
  354.                                         ;  leftarrow, rightarrow and uparrow
  355.                                         ; first the Z-100 numeric keypad
  356. kbdinlst equ    this byte               ; mkeyw 'definition',keycode
  357.         mkeyw   '\khomscn',scan+0a9h    ; home key
  358.         mkeyw   '\klfarr',scan+0a8h     ; leftarrow
  359.         mkeyw   '\krtarr',scan+0a7h     ; rightarrow
  360.         mkeyw   '\kuparr',scan+0a5h     ; uparrow
  361.         mkeyw   '\kkp7',scan+0b7h       ; kp7
  362.         mkeyw   '\kkp8',scan+0b8h       ; kp8
  363.         mkeyw   '\kkp9',scan+0b9h       ; kp9
  364.         mkeyw   '\kdnarr',scan+0a6h     ; downarrow
  365.         mkeyw   '\kkp4',scan+0b4h       ; kp4
  366.         mkeyw   '\kkp5',scan+0b5h       ; kp5
  367.         mkeyw   '\kkp6',scan+0b6h       ; kp6
  368.         mkeyw   '\kkpminus',scan+0adh   ; kp minus
  369.         mkeyw   '\kkp1',scan+0b1h       ; kp1
  370.         mkeyw   '\kkp2',scan+0b2h       ; kp2
  371.         mkeyw   '\kkp3',scan+0b3h       ; kp3
  372.         mkeyw   '\kkpenter',scan+08dh   ; Enter key
  373.         mkeyw   '\kkp0',scan+0b0h       ; kp0
  374.         mkeyw   '\kkpdot',scan+0aeh     ; kp dot
  375.         mkeyw   '\kgold',scan+shift+0e9h; shifted home key      => VT100 gold
  376.         mkeyw   '\kpf2',scan+shift+0e8h ; shifted left arrow    => VT100 PF2
  377.         mkeyw   '\kpf3',scan+shift+0e7h ; shifted right arrow   => VT100 PF3
  378.         mkeyw   '\kpf4',scan+shift+0e5h ; shifted up arrow      => VT100 PF4
  379.         mkeyw   '\kd_chr',scan+shift+0f7h   ; shifted kp7
  380.         mkeyw   '\kuparr',scan+shift+0f8h   ; shifted kp8
  381.         mkeyw   '\ki_chr',scan+shift+0f9h   ; shifted kp9
  382.         mkeyw   '\kkpminus',scan+shift+0e6h ; shifted down arrow => VT100 minus
  383.         mkeyw   '\klfarr',scan+shift+0f4h   ; shifted kp4
  384.         mkeyw   '\khomscn',scan+shift+0f5h  ; shifted kp5
  385.         mkeyw   '\krtarr',scan+shift+0f6h   ; shifted kp6
  386.         mkeyw   '\kkpcoma',scan+shift+0edh  ; shifted kp minus   => VT100 comma
  387.         mkeyw   '\ki_line',scan+shift+0f1h  ; shifted kp1
  388.         mkeyw   '\kdnarr',scan+shift+0f2h   ; shifted kp2
  389.         mkeyw   '\kd_line',scan+shift+0f3h  ; shifted kp3
  390.         mkeyw   '\x0d',scan+shift+0cdh      ; shifted enter
  391.         mkeyw   '0',scan+shift+0f0h         ; shifted kp0
  392.         mkeyw   '.',scan+shift+0eeh         ; shifted kp dot
  393.                                         ; Some function keys
  394.                                         ; VT100 function keys
  395.         mkeyw   '\kf0',scan+096h        ; F0
  396.         mkeyw   '\kf1',scan+097h        ; F1
  397.         mkeyw   '\kf2',scan+098h        ; F2
  398.         mkeyw   '\kf3',scan+099h        ; F3
  399.         mkeyw   '\kf4',scan+09ah        ; F4
  400.         mkeyw   '\kf5',scan+09bh        ; F5
  401.         mkeyw   '\kf6',scan+09ch        ; F6
  402.         mkeyw   '\kf7',scan+09dh        ; F7
  403.         mkeyw   '\kf8',scan+09eh        ; F8
  404.         mkeyw   '\kf9',scan+09fh        ; F9
  405.         mkeyw   '\kf10',scan+0a0h       ; F10
  406.     mkeyw    '\kscroll',scan+0a1h    ; F11 Recover last screen
  407.         mkeyw   '\kprtscn',scan+0a2h    ; F12 Kermit toggle prn scrn
  408.         mkeyw   '\ksf0',scan+shift+0d6h ; SF0
  409.         mkeyw   '\ksf1',scan+shift+0d7h ; SF1
  410.         mkeyw   '\ksf2',scan+shift+0d8h ; SF2
  411.         mkeyw   '\ksf3',scan+shift+0d9h ; SF3
  412.         mkeyw   '\ksf4',scan+shift+0dah ; SF4
  413.         mkeyw   '\ksf5',scan+shift+0dbh ; SF5
  414.         mkeyw   '\ksf6',scan+shift+0dch ; SF6
  415.         mkeyw   '\ksf7',scan+shift+0ddh ; SF7
  416.         mkeyw   '\ksf8',scan+shift+0deh ; SF8
  417.         mkeyw   '\ksf9',scan+shift+0dfh ; SF9
  418.         mkeyw   '\ksf10',scan+shift+0e0h; SF10
  419.         mkeyw   '\kdump',scan+shift+0e1h; SF11 Kermit Dump Screen
  420.                     ; SF12 not available, used by DOS prtscr
  421.                                         ; Some special keys
  422.         mkeyw   '\klbreak',scan+shift+0eah; Shift-Break sends a Long Break
  423.         mkeyw   '\khelp',scan+095h        ; Connect mode drop down menu
  424.         mkeyw   '\kstatus',scan+shift+0d5h; Display Status
  425. ;       mkeyw   '\kdnone',scan+0a3h       ; I CHR  scrolls down 1 line
  426. ;       mkeyw   '\kupone',scan+shift+0e3h ; D CHR  scrolls up   1 line
  427. ;       mkeyw   '\kdnscn',scan+0a4h       ; I LINE scrolls down 1 page
  428. ;       mkeyw   '\kupscn',scan+shift+0e4h ; D LINE scrolls up   1 page
  429.         mkeyw   '\ki_chr',scan+0a3h       ; I CHR  sends ESC @ or ESC O
  430.         mkeyw   '\kd_chr',scan+shift+0e3h ; D CHR  sends ESC N
  431.         mkeyw   '\ki_line',scan+0a4h      ; I LINE sends ESC L
  432.         mkeyw   '\kd_line',scan+shift+0e4h; D LINE sends ESC M
  433.         dw      0                       ; end of table marker
  434.  
  435. kbcodes dw      80h                     ; keyboard read codes, 80h=not inited
  436.  
  437. data    ends
  438.  
  439. ;                       Documentation
  440. ;Translating a key:
  441. ;   The translator is called to obtain keyboard input; it sends characters to
  442. ; the serial port through standard controlled echo procedures or invokes
  443. ; named procedures. It returns carry clear when its operation is completed
  444. ; for normal actions and carry set when Connect mode must be exited. When
  445. ; Connect mode is exited the just read char should be passed in Kbdflg 
  446. ; to msster.asm for invoking actions such as Status, send a break,
  447. ; quit connect mode; system dependent procedure Term is responsible for this. 
  448. ;
  449. ;  Principal procedures are -
  450. ;       msuinit         Initializes keyboard translator in this file when
  451. ;                       Kermit first begins. Installs dfkey and shkey as the
  452. ;                       procedures used for Set Key and Show Key. Sys Indep.
  453. ;                       Called from msx or msy init procs. System Independent.
  454. ;       keybd           Performs the translation, outputs chars to the serial
  455. ;                       port or invokes a Kermit action routine. Sys Indep.
  456. ;       dfkey           Defines a key's translation. Reads command line
  457. ;                       via Kermit's command parser comnd. System Independent.
  458. ;       shkey           Shows translation of a key. Requests user to push
  459. ;                       selected key. System Independent.
  460. ;
  461. ;       kbdinit         optional. Initializes the translation tables when
  462. ;                       Kermit starts up. Called by msuinit. System Dependent.
  463. ;       getkey          Performs the keyboard read and returns results in
  464. ;                       a standardized system independent format. Sys Depend.
  465. ;       postkey         called by active translator after obtaining a keycode.
  466. ;                       Used to provide extra local actions (keyclick) only
  467. ;                       in Connect mode (not during Set/Show key commands).
  468. ;                       Called by keybd. System dependent.
  469. ; Supporting system independent procedures are -
  470. ; shkfre (show string free space), tstkeyw (finds user's keyword in the verb
  471. ; table), insertst (insert string in buffer), remstr (delete string in buffer).
  472. ;
  473. ;   System dependent procedure Getkey reads a keycode (usually via a Bios
  474. ; call). On IBM compatible machines this yields <ah=scan code, al=ascii>
  475. ; for ordinary keys, or <ah=scan code, al=0> for special keys such as F1,
  476. ; or <ah=0, al=###> when Alt### is used.
  477. ; For any system, the canonical output form is the key's code in Keycode.
  478. ; Place the ascii code (or scan code if none) in byte Keycode and ancillary
  479. ; info (shift states plus marker bit for scan codes) in byte Keycode + 1.
  480. ;    Procedure Keybd calls Getkey for the Keycode, checks list of translatable
  481. ; keys Keylist, and then either sends an ascii string (one or more characters)
  482. ; or invokes a Kermit action verb. List Dirlist indicates what kind of 
  483. ; translation to do. Keybd is system independent but may contain system
  484. ; dependent special actions such as echoing keyclicks. Keybd calls system
  485. ; dependent procedure Postkey just after calling getkey so local actions
  486. ; such as keyclicks can be activated only during Connect mode operations.
  487. ;
  488. ;    Keylist is a packed but unordered list of 16 bit keycodes which need
  489. ; translation. The lower order byte holds a key code (ascii char or scan code)
  490. ; while the high byte holds a scan code marker bit (0 if ascii code in low
  491. ; byte) plus any ancillary keyboard information such as Control/Shift/Alt/Meta
  492. ; keys being held down; these are of use in Show Key presentations.
  493. ;    Dirlist parallels Keylist to provide the kind of translation, verb or
  494. ; string, in the two highest bits with the other bits holding either
  495. ; a single new replacement character or the item number in lists of verbs
  496. ; or strings. If neither verb nor strng type bits are set in a dirlist
  497. ; word then the translation is a single new character held in the lower
  498. ; eight bits of that dirlist word.
  499. ;
  500. ;    The number of key translations is assembly constant Maxkeys (def 128).
  501. ;    The maximum number of strings is assembly constant Maxstngs (def 64).
  502. ;    The maximum number of verbs is 256 and is set by building table Kverbs.
  503. ;
  504. ;   For verbs, use the Item number from the Director table Dirlist to select
  505. ; a procedure offset from the structured list Kverbs and jump to that offset.
  506. ; Most verb procedures return carry clear to stay within Connect mode.
  507. ; Verbs requiring exiting Connect mode return carry set and may set byte
  508. ; Kbdflg to a char code which will be read by msster.asm for activating a
  509. ; transient Kermit action such as send a break (Kbdflg = 'b').
  510. ; Kbdflg is stored in msster.asm (as zero initially, meaning ignore it).
  511. ; Action verb procedures are normally located in a system dependent file.
  512. ;
  513. ;   For multi-char strings, use Item number from Director table Dirlist to
  514. ; select a pointer to a string. The list of string pointers is Sptable
  515. ; (string pointer table) which holds the offset in the data segment of the
  516. ; strings stored in buffer Stbuf. In stbuf strings are held as: one byte of
  517. ; length of following text and then the text itself (permits embedded nulls).
  518. ;  Use Chrout to send each string character, and finally return from Keybd
  519. ; with carry clear.
  520. ;
  521. ;   For single character replacements obtain the new character from the lower
  522. ; order byte of Director table Dirlist. If the character is Kermit's present
  523. ; escape character return from Keybd carry set to leave connect mode.
  524. ; Otherwise, send the character via Chrout and return from Keybd carry clear.
  525.  
  526. ; Keylist table format:
  527. ;    7 bits   1 bit   8 bits
  528. ; +----------+----+------------+ scan bit = 1 if key's code is non-ascii
  529. ; | aux info |scan| key's code | aux info = system dependent, used only to
  530. ; +----------+----+------------+            help identify key
  531. ;
  532. ; Dirlist table format            v s   meaning
  533. ;   1   1      14 bits            0 0   copy out one byte translation
  534. ; +---+---+--------------------+  1 0   copy out multi-char string number Item
  535. ; | v | s | item # or new char |  0 1   do action verb number Item
  536. ; +---+---+--------------------+  1 1   (not used)
  537. ;
  538. ; Table kverbs is organized by macro mkeyw as -
  539. ;       kverbs  db      number of table entries
  540. ;       (each entry is in the form below:)
  541. ;               db      number of bytes in verbname
  542. ;               db      'verbname'              variable length
  543. ;               db      '$'                     for printing
  544. ;               dw      value                   offset of procedure
  545. ;
  546. ;
  547. ;   Dfkey defines a key to be itself (undefines it) or a single replacement
  548. ; character or a character string or a Kermit action verb. Dfkey requires
  549. ; a command line so that it may be invoked by Take files but can be forced
  550. ; to prompt an interactive user to push a key. Syntax is discussed below.
  551. ; Note that redefined keys have their old definitions cleared so that
  552. ; old string space is reclaimed automatically.
  553. ;
  554. ;   Shkey displays a key's definition and the user is asked to push the
  555. ; selected key. The free space for strings is always shown afterward. See
  556. ; below for syntax.
  557. ;
  558. ;   Kbdinit is an optional routine called when Kermit starts up. It fills in
  559. ; the translation tables with desirable default values to save having to
  560. ; use long mskermit.ini files. The default values are stored in a structured
  561. ; table similar to (but not the same as) Dfkey's command lines; the keycode
  562. ; values are preset by hand to 16 bit numbers.
  563.  
  564. ;Defining a key:
  565. ; Command is SET KEY <key ident><whitespace><definition>
  566. ;
  567. ; <key ident> is
  568. ;               a single ordinary ascii char or
  569. ;               the numerical equivalent of an ascii char or
  570. ;               a Scan Code written as a number or
  571. ;               keyword SCAN followed by a number.
  572. ;               ?       Displays help message.
  573. ;       Numbers and Binary codes are of the form
  574. ;               \123    a decimal number
  575. ;               \o456   an octal number         base letters o, d, x can be
  576. ;               \d213   a decimal number        upper or lower case
  577. ;               \x0d    a hex number
  578. ;               \{b###}  braces around above material following slash.
  579. ;
  580. ; <whitespace> is one or more spaces and or tabs.
  581. ;
  582. ; <definition> is
  583. ;       missing altogether which "undefines" a key.
  584. ;       \Kverb          for a Kermit action verb; upper or lower case K is ok
  585. ;       \{Kverb}        ditto. Verb is the name of an action verb.
  586. ;       text            a string with allowed embedded whitespace and embedded
  587. ;                       binary chars as above. This kind of string may not
  588. ;                       commence with sequences \K or \{K; use braces below.
  589. ;       {text}          string confined to material within but excluding
  590. ;                       the braces. Note, where the number of opening braces
  591. ;                       exceeds the number of closing braces the end of line
  592. ;                       terminates the string: {ab{}{{c}d ==> ab{}{{c}d
  593. ;                       but  {ab}{{c}d ==> ab.
  594. ;       ?               Displays help message and lists all action verbs.
  595. ;
  596. ;       If Set Key is given interactively, as opposed to within a Take
  597. ;       file, the system will prompt for inputs if none is on the command
  598. ;       line. The response to Push key to be defined cannot be edited.
  599. ;
  600. ;       Text which reduces to a single replacement character is put into a
  601. ;       table separate from the multi-character strings (maxstng of these).
  602. ;       A key may be translated into any single 8 bit code.
  603. ;       
  604. ;       Comments can follow a Kermit action verb or a braced string; no
  605. ;       semicolon is required since all are stripped out by the Take file
  606. ;       reader before the defining text is seen by SET KEY.
  607. ;
  608. ;       The current Kermit escape character cannot be translated without
  609. ;       subtrafuge.
  610. ;
  611. ;       Examples:
  612. ;               Set Key q z
  613. ;                               makes key q send character z
  614. ;               Set Key \7 \27[0m
  615. ;                               makes key Control G send the four byte
  616. ;                               string  ESC [ 0 m
  617. ;               Set Key q
  618. ;                               undefines key q so it sends itself (q) again.
  619. ;               Set Key \2349 \kexit
  620. ;                               defines IBM Alt-X to invoke the leave connect
  621. ;                               mode verb "exit" (Kermit's escape-char ^] C).
  622. ;               Set Key \x0c Login \{x0d}myname\{x0d}mypass\x0d
  623. ;                               defines Control L to send the string
  624. ;                               Login <cr>myname<cr>mypass<cr>
  625. ;
  626. ; Alternative Set Key syntax for backward compatibility with previous versions
  627. ;       The same forms as above except the key identification number must
  628. ;       be decimal and must Not have a leading backslash. Example:
  629. ;       Set Key Scan 59 This is the F1 key
  630. ;
  631. ;       If the definition is omitted it may be placed on the following line;
  632. ;       if that line is also empty the key is undefined (defined as Self).
  633. ;       A warning message about obsolete syntax will be given followed by
  634. ;       the key's modern numerical value and new definition. Only "special"
  635. ;       keys (those not producing ascii codes) are compatible with this
  636. ;       translator.
  637. ;
  638. ;Showing a key:
  639. ; Command is SHOW KEY <cr>
  640. ; System prompts user to press a key and shows the definition plus the
  641. ; free space for strings. Query response results in showing all definitions.
  642. ;                       End Documentation
  643.  
  644. code    segment
  645.                 ; system independent external items
  646.         extrn   comnd:near, prompt:near, iseof:near     ; in msscmd
  647.         extrn   strlen:near, prtscr:near        ; in mssfil
  648.         extrn   cnvlin:near, katoi:near, decout:near    ; in msster
  649.                 ; system dependent external items
  650.         extrn   beep:near, ena_scan:near, dis_scan:near ; in msxz10
  651.         extrn   vclick:near                             ; in msxz10
  652.                 ; these are system dependent action verbs, in msxibm & msyibm 
  653.         extrn   f0:near, f1:near, f2:near, f3:near, f4:near, f5:near, f6:near
  654.         extrn   f7:near, f8:near, f9:near, f10:near, f11:near, f12:near
  655.         extrn   sf0:near, sf1:near, sf2:near, sf3:near, sf4:near, sf5:near
  656.         extrn   sf6:near, sf7:near, sf8:near, sf9:near, sf10:near, sf11:near
  657.         extrn   i_chr:near, d_chr:near, i_line:near, d_line:near
  658.         extrn   uparrw:near, dnarrw:near, rtarr:near, lfarr:near
  659.         extrn   pf1:near, pf2:near, pf3:near, pf4:near, kp0:near, kp1:near
  660.         extrn   kp2:near, kp3:near, kp4:near, kp5:near, kp6:near, kp7:near
  661.         extrn   kp8:near, kp9:near, kpminus:near, kpcoma:near, kpenter:near
  662.         extrn   kpdot:near, dnwpg:near, upwpg:near, scroll:near
  663. comment @
  664.         extrn   kpdot:near, decf6:near, decf7:near, decf8:near, decf9:near
  665.         extrn   decf10:near, decf11:near, decf12:near, decf13:near
  666.         extrn   decf14:near, dechelp:near, decdo:near, decf17:near
  667.         extrn   decf18:near, decf19:near, decf20:near, udkclear:near
  668.         extrn   decfind:near, decinsert:near, decremove:near
  669.         extrn   decselect:near, decprev:near, decnext:near
  670.         extrn   chrout:near, cstatus:near, cquit:near, cquery:near
  671.         extrn   vtans52:near, vtinit:near, dnwpg:near, upwpg:near
  672. end comment @
  673.         extrn   endwnd:near, homwnd:near, upone:near, dnone:near, trnprs:near
  674.         extrn   chang:near, klogon:near, klogof:near
  675.         extrn   trnmod:near, sendbr:near, sendbl:near, dmpscn:near, snull:near
  676.         extrn   cplatin:near, nrc2cp:near
  677.         extrn   cpdecsg:near, cdos:near, cquery:near, cstatus:near
  678.         extrn   chrout:near, cquit:near, udkclear:near, extmacro:near
  679.         assume  cs:code, ds:data, es:data
  680.  
  681. ; Begin system independent Keyboard Translator code
  682.  
  683. ; MSUINIT performs Kermit startup initialization for this file.
  684. ; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
  685. ; are not initialized here then the older Set/Show Key procedures are called.
  686. MSUINIT PROC    NEAR                    ; call from msx/msy init code
  687.         call    kbdinit                 ; optional: init translator tables
  688.         mov     shkadr,offset shkey     ; declare keyboard translator present
  689.         mov     stkadr,offset dfkey     ; via Show and Set Key proc addresses
  690.         ret
  691. MSUINIT ENDP
  692.  
  693. ; Call Keybd to read a keyboard char (just returns carry clear if none) and
  694. ; 1) send the replacement string (or original char if not translated)
  695. ;    out the serial port, or
  696. ; 2) execute a Kermit action verb.
  697. ; Returns carry set if Connect mode is to be exited, else carry clear.
  698. ; Modifies registers ax and bx. 
  699. KEYBD   PROC    NEAR                    ; active translator
  700.         mov     ttyact,1                ; doing single char output
  701.         cmp     stringcnt,0             ; any leftover string chars?
  702.         je      keybd0                  ; e = no
  703.         jmp     keyst2                  ; yes, finish string
  704. keybd0: call    getkey                  ; read keyboard
  705.         jnc     keybd1                  ; nc = data available
  706.         jmp     keybdx                  ; else just return carry clear
  707. keybd1: call    postkey                 ; call system dependent post processor
  708.         cmp     nkeys,0                 ; is number of keys defined = 0?
  709.         jz      keybd3                  ; z = none defined
  710.         push    di                      ; search keylist for this keycode
  711.         push    cx                      ; save some registers   
  712.         push    es
  713.         mov     di,offset keylist       ; list of defined keycode words
  714.         mov     ax,keycode              ; present keycode
  715.         mov     cx,nkeys                ; number of words to examine
  716.         push    ds
  717.         pop     es                      ; make es:di point to data segment
  718.         cld
  719.         repne   scasw                   ; find keycode in list
  720.         pop     es                      ; restore regs
  721.         pop     cx
  722.         je      keybd1b                 ; e = found, work with present di
  723.         pop     di                      ; restore original di
  724.         test    keycode,scan            ; is this a scan code?
  725.         jz      keybd3                  ; z = no, it's ascii, use al as char
  726.         call    beep                    ; say key is a dead one
  727.         clc
  728.         ret                             ; and exit with no action
  729.  
  730. keybd1b:sub     di,2                    ; correct for auto increment
  731.         sub     di,offset keylist       ; subtract start of list ==> listptr
  732.         mov     ax,dirlist[di]          ; ax = contents of director word
  733.         pop     di                      ; restore original di
  734.                                         ; dispatch on Director code
  735.         test    ax,verb                 ; verb only?
  736.         jnz     keyvb                   ; e = yes
  737.         test    ax,strng                ; multi-char string only?
  738.         jnz     keyst                   ; e = yes, else single char & no xlat.
  739.                                         ;
  740.                                         ; do single CHAR output (char in al)
  741. keybd3: cmp     al,trans.escchr         ; Kermit's escape char?
  742.         je      keybd3a                 ; e = yes, handle separately
  743.         call    xltkey                  ; do character set translation
  744.         call    chrout                  ; transmit the char
  745.         clc                             ; return success
  746.         ret
  747. keybd3a:stc                             ; set carry for jump to Quit
  748.         ret
  749.  
  750. keyvb:  and     ax,not(verb+strng)      ; VERB (ax=index, remove type bits)
  751.         mov     bx,offset kverbs        ; start of verb table
  752.         cmp     al,byte ptr [bx]        ; index > number of entries?
  753.         jae     keybdx                  ; ae = illegal, indices start at 0
  754.         inc     bx                      ; bx points to first entry
  755.         push    cx                      ; save reg
  756.         mov     cx,ax                   ; save the index in cx
  757.         inc     cx                      ; counter, indices start at 0
  758. keyvb1: mov     ax,[bx]            ; cnt value
  759.         add     ax,4                    ; skip text and value word
  760.         add     bx,ax                   ; look at next slot
  761.         loop    keyvb1                  ; walk to correct slot
  762.         sub     bx,2                    ; backup to value field
  763.         pop     cx                      ; restore reg
  764.         mov     bx,[bx]                 ; get value field of this slot
  765.         or    bx,bx            ; jump address defined?
  766.         jz      keybdx                  ; z = no, skip the action
  767.         jmp     bx                      ; perform the function
  768.  
  769. keyst:  and     ax,not(verb+strng)      ; STRING (ax=index, remove type bits)
  770.         shl     ax,1                    ; convert to word index
  771.         push    si                      ; save working reg
  772.         mov     si,ax                   ; word subscript in table
  773.         mov     si,sptable[si]          ; memory offset of selected string
  774.         xor     cx,cx                   ; init string length to null
  775.         or    si,si            ; is there a string pointer present?
  776.         jz      keyst1                  ; z = no, skip operation
  777.         cld                             ; scan forward
  778.         mov     cx,[si]            ; get string length
  779.         add     si,2
  780. keyst1: mov     stringcnt,cx
  781.         mov     stringptr,si
  782.         pop     si
  783.         jcxz    keybdx                  ; z = null length
  784.  
  785. keyst2: push    si
  786.         mov     si,stringptr            ; pointer to next string char
  787.         cld
  788.         lodsb                           ; get new string char into al
  789.         pop     si
  790.         dec     stringcnt               ; string chars remaining
  791.         inc     stringptr
  792.     call    keysv            ; scan for embedded verbs
  793.     jc    keyst4            ; c = not found, al has string char
  794.     jmp    bx            ; perform the verb (bx = address)
  795. keyst4:    cmp     stringcnt,0             ; end of the string?
  796.         jne     keyst5                  ; ne = no
  797.         mov     ttyact,0                ; pretend not single char output
  798. keyst5:    jmp     chrout                  ; send out the char in al
  799.  
  800. keybdx: clc                             ; return success (nothing to do)
  801.         ret
  802. KEYBD   ENDP
  803.  
  804. ; Scan for keyboard verbs embedded in outgoing string. If found update
  805. ; string pointer and count to just beyond the verb and return action routine
  806. ; address in bx with carry clear. If failure return carry set and no change.
  807.  
  808. keysv   proc    near
  809.         push    ax
  810.         push    si
  811.         push    di
  812.         cmp     al,'\'                  ; escape?
  813.         jne     keysv7                  ; ne = no
  814.         mov     cx,stringcnt            ; chars remaining
  815.         mov     si,stringptr            ; address of next char to read
  816.         mov     brace,0                 ; assume not using braces
  817.         cmp     byte ptr [si],braceop   ; starts with \{?
  818.         jne     keysv1                  ; ne = no
  819.         inc     si                      ; skip the opening brace
  820.         dec     cx
  821.         mov     brace,bracecl           ; expect closing brace
  822. keysv1: cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  823.         je      keysv2                  ; e = yes
  824.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  825.         jne     keysv7                  ; ne = no, then it's a string
  826. keysv2: inc     si                      ; yes, skip the K too
  827.         dec     cx
  828.         mov     di,offset tranbuf       ; copy verb name to this work buffer
  829.         xor     ax,ax
  830.         mov     [di],ax                 ; init the buffer to empty
  831. keysv3: cld
  832.         jcxz    keysv4                  ; z = no more string chars
  833.         lodsb                           ; scan til closing brace or w/s or end
  834.         dec     cx
  835.         cmp     al,brace                ; closing brace?
  836.         je      keysv4                  ; e = yes
  837.         cmp     al,spc                  ; white space or control char?
  838.         jbe     keysv3                  ; be = yes
  839.         mov     [di],ax                 ; copy to tranbuf and terminate
  840.         inc     di
  841.         jmp     short keysv3
  842. keysv4:    push    si            ; save input reading position
  843.     mov    si,offset tranbuf    ; where verb starts (needs si)
  844.     call    tstkeyw            ; find keyword, bx = action routine
  845.     pop    si
  846.     jnc    keysv4a            ; nc = found the verb
  847.     call    keysv8            ; invoke EXTMACRO worker for unknown
  848.     jc    keysv7            ; carry = no verb to operate upon
  849. keysv4a:cmp    brace,0            ; need to end on a brace?
  850.     je    keysv6            ; e = no
  851.     dec    si            ; break position
  852.     inc    cx
  853.     cld
  854. keysv5:    jcxz    keysv6            ; z = no more string characters
  855.     lodsb                ; read string char
  856.     dec    cx
  857.     cmp    al,brace        ; the brace?
  858.     jne    keysv5            ; ne = no, repeat until it is found
  859. keysv6:    mov    stringptr,si        ; where we finished+1
  860.     mov    stringcnt,cx        ; new count of remaining chars
  861.     pop    di
  862.     pop    si            ; original si, starting place
  863.     pop    ax            ; original ax
  864.     clc
  865.     ret
  866. keysv7:    pop    di            ; verb not found
  867.     pop    si
  868.     pop    ax
  869.     stc
  870.     ret
  871. ; Worker. Unknown verb name as string {\kverb} or {\k{verb}}. Use EXTMACRO
  872. ; procedure (in msyibm typically), point to verb name with vtmacname, length
  873. ; of it in byte vtmaclen, address of EXTMACRO to BX. Upper case the verb.
  874. ; Enter with tranbuf holding the verb, asciiz, without \K and braces.
  875. ; Returns BX set to EXTMACRO proc, vtmacname pointing to verb (uppercased)
  876. ; and vtmaclen holding the length of verb.
  877. keysv8:    mov    bx,offset extmacro    ; use this external macro pointer
  878.     mov    vtmacname,offset tranbuf; select extmacro procedure address
  879.     mov    dx,offset tranbuf    ; point to name for extmacro
  880.     push    cx
  881.     call    strlen            ; get its length
  882.     mov    vtmaclen,cx        ; length for extmacro
  883.     jcxz    keysv11            ; z = none
  884.     push    si            ; convert verb name to upper case
  885.     mov    si,dx            ; verb, without leading \K stuff
  886.     cld
  887. keysv9:    lodsb                ; read a name byte
  888.     cmp    al,'a'            ; before lower case?
  889.     jb    keysv10            ; e = yes
  890.     cmp    al,'z'            ; above lower case?
  891.     ja    keysv10            ; a = yes
  892.     and    al,not 20h        ; convert to upper case
  893.     mov    [si-1],al        ; put it back
  894. keysv10:loop    keysv9            ; do all bytes, asciiz
  895.     pop    si
  896.     pop    cx
  897.     clc                ; carry clear = ready to execute
  898.     ret
  899. keysv11:stc                ; carry set = no verb, do nothing
  900.     pop    cx
  901.     ret
  902. keysv   endp
  903.  
  904. ; SET KEY - define a key   (procedure dfkey)
  905. ; SET KEY <key ident><whitespace><new meaning>
  906. ; Call from Kermit level. Returns as ret if failure or as rskp if success.
  907. ;  
  908. DFKEY   PROC    NEAR                    ; define a key as a verb or a string
  909.         mov     keycode,0               ; clear keycode
  910.         mov     oldform,0               ; say no old form Set Key yet
  911.         or      byte ptr kbcodes,80h    ; say kbcodes not-initiated
  912.         mov     dx,offset tranbuf       ; our work space
  913.         mov     word ptr tranbuf,0      ; insert terminator
  914.         mov     bx,offset dfhelp1       ; first help message
  915.         mov     ah,cmword               ; parse a word
  916.         call    comnd                   ; get key code or original ascii char
  917.         mov     cl,taklev               ; reading from Take file
  918.         mov     msutake,cl              ; save here
  919.         or      ax,ax                   ; any text given?
  920.         jnz     dfkey12                 ; nz = yes, so don't consider prompts
  921.                                         ; interactive key request
  922.         cmp     taklev,0                ; in a Take file?
  923.         je      dfkey10                 ; e = no, prompt for keystroke
  924.         jmp     dfkey0                  ;  else say bad syntax
  925. dfkey10:mov     ah,prstr
  926.         mov     dx,offset dfaskky       ; ask for key to be pressed
  927.         int     dos
  928. dfkey11:call    getkey                  ; read key ident from keyboard
  929.         jc      dfkey11                 ; c = no response, wait for keystroke
  930.         mov     ah,prstr                ; display cr/lf
  931.         mov     dx,offset crlf
  932.         int     dos
  933.         call    shkey0                  ; show current definition (in SHKEY)
  934.         jmp     dfkey1e                 ; prompt for and process definition
  935.  
  936. dfkey12:                                ; Look for word SCAN and ignore it
  937.         mov     dx,word ptr tranbuf     ; get first two characters
  938.         or      dx,2020h                ; map upper to lower case
  939.         cmp     dx,'cs'                 ; first two letters of word "scan"?
  940.         je      dfkey                   ; e = yes, skip the word
  941.         cmp     dx,'lc'                 ; first two letters of word "clear"?
  942.         je      dfkey15                 ; e = yes, reinit keyboard [2.31]
  943.         cmp     dx,'fo'                 ; first two letters of "off"
  944.         je      dfkey13                 ; e = yes, use DOS keyboard calls
  945.         cmp     dx,'no'                 ; first two letters of "on"
  946.         je      dfkey14                 ; e = yes, use standard kbd calls
  947.     cmp    ax,1            ; number of characters received
  948.     jbe    dfkey12a        ; be = stay here
  949.     jmp    dfkey1            ; a = more than one, decode
  950. dfkey12a:mov    ah,byte ptr tranbuf    ; get the single char
  951.     mov    byte ptr keycode,ah    ; store as ascii keycode
  952.     jmp    dfkey1b            ; go get definition
  953. dfkey13:push    dx            ; save command letters
  954.     mov    ah,cmeol        ; get end of line confirmation
  955.     call    comnd
  956.     pop    dx
  957.     jnc    dfkey14            ; nc = success
  958.     ret
  959. dfkey14:mov    al,0ffh            ; set DOS keyboard read flag
  960.     cmp    dx,'fo'            ; first two letters of "off"
  961.     je    dfkey14a        ; e = yes, use DOS keyboard calls
  962.     xor    al,al            ; clear DOS keyboard read flag
  963.     cmp    dx,'no'            ; first two letters of "on"
  964.     je    dfkey14a        ; e = yes, use standard kbd calls
  965.     mov    al,dosflg        ; get current flag
  966. dfkey14a:mov    dosflg,al        ; store new keyboard flag
  967.     ret
  968.  
  969.  
  970. dfkey15:mov     ah,cmeol
  971.         call    comnd                   ; confirm request before proceeding
  972.         jnc     dfkeyc                  ; nc = success
  973.         ret                             ; failure
  974.  
  975. dfkey0: mov     dx,offset dfhelp1       ; say bad definition command
  976.         mov     ah,prstr
  977.         int     dos
  978.         stc                             ; failure
  979.         ret
  980.  
  981. dfkeyc:                                 ; CLEAR key defs, restore startup defs
  982.         mov     cx,maxkeys              ; size of keycode tables
  983.         push    es                      ; save register
  984.         push    ds
  985.         pop     es                      ; make es point to data segment
  986.         xor    ax,ax                   ; null, value to be stored
  987.         mov     di,offset dirlist       ; director table
  988.         cld
  989.         rep     stosw                   ; clear it
  990.         mov     cx,maxkeys
  991.         mov     di,offset keylist       ; keycode table
  992.         rep     stosw                   ; clear it
  993.         mov     cx,maxstng
  994.         mov     di,offset sptable       ; string pointer table
  995.         rep     stosw                   ; clear it
  996.         pop     es                      ; recover register
  997.         mov     strmax,offset stbuf     ; clear string buffer, free space ptr
  998.         mov     stbuf,0                 ; first element of buffer 
  999.         mov     nkeys,0                 ; clear number of defined keys
  1000.         call    msuinit                 ; restore startup definitions
  1001.         clc                             ; success
  1002.         ret
  1003.                                         ; Multi-char key identification
  1004. dfkey1: mov     si,offset tranbuf       ; point to key ident text
  1005.         cmp     byte ptr [si],'0'       ; is first character numeric?
  1006.         jb      dfkey1a                 ; b = no
  1007.         cmp     byte ptr [si],'9'       ; in numbers?
  1008.         ja      dfkey1a                 ; a = no
  1009.         mov     keycode,scan            ; setup keycode for scan value
  1010.         mov     dx,si                   ; get length of string in cx
  1011.         call    strlen
  1012.         push    ds
  1013.         pop     es                      ; make es point to data segment
  1014.         push    si
  1015.         add     si,cx                   ; point at string terminator
  1016.         mov     di,si
  1017.         inc     di                      ; place to store string (1 byte later)
  1018.         inc     cx                      ; include null terminator
  1019.         std                             ; work backward
  1020.         rep     movsb                   ; move string one place later
  1021.         cld
  1022.         pop     si
  1023.         mov     byte ptr [si],'\'       ; make ascii digits into \nnn form
  1024.         mov     oldform,0ffh            ; set old form flag
  1025.         mov     dx,offset kwarnmsg      ; tell user this is old form
  1026.         mov     ah,prstr
  1027.         int     dos
  1028. dfkey1a:call    katoi                   ; convert ascii number to binary in ax
  1029.         jc      dfkey0                  ; c = no number converted
  1030.         or      keycode,ax              ; store in keycode
  1031.  
  1032. dfkey1b:                                ; Get Definition proper
  1033.         test    oldform,0ffh            ; old form Set Key active?
  1034.         jz      dfkey1f                 ; z = no
  1035.         mov     bx,offset tranbuf       ; get new definition on main cmd line
  1036.         mov     word ptr [bx],0         ; insert terminator
  1037.         mov     dx,offset dfhelp2       ; help for definition of key
  1038.         mov     ah,cmline               ; read rest of line into tranbuf
  1039.         call    comnd                   ; allow null definitions
  1040.         or      ax,ax                   ; char count zero?
  1041.         jz      dfkey1e                 ; z = zero, prompt for definition
  1042.         jmp     dfkey1g                 ; process definition
  1043.  
  1044. dfkey1e:mov     ah,prstr
  1045.         mov     dx,offset crlf
  1046.         int     dos
  1047.         mov     dx,offset dfaskdf       ; prompt for definition string
  1048.         call    prompt                  ; Kermit prompt routine
  1049.         mov     comand.cmcr,1           ; permit bare carriage returns
  1050.         mov     comand.cmwhite,1        ; allow leading whitespace
  1051. dfkey1f:mov     bx,offset tranbuf       ; get new definition
  1052.         mov     word ptr [bx],0         ; insert terminator
  1053.         mov     dx,offset dfhelp2       ; help for definition of key
  1054.         mov     ah,cmline               ; read rest of line into tranbuf
  1055.         call    comnd
  1056.         jc      dfkey1x                 ; exit now on ^C from user
  1057.         cmp     comand.cmcr,0           ; prompting for definition?
  1058.         je      dfkey1g                 ; e = no, trim leading whitespace
  1059.         mov     comand.cmcr,0           ; turn off allowance for bare c/r's
  1060.         jmp     dfkey2                  ; interactive, allow leading whitespace
  1061. dfkey1x:ret                             ; failure exit
  1062.  
  1063. dfkey1g:push    ax            ; save count
  1064.         mov     ah,cmeol                ; get a confirm
  1065.         call    comnd
  1066.         pop     cx            ; string length
  1067.         jc      dfkey1x                 ; none so declare parse error
  1068.         
  1069. dfkey2:                                 ; Examine translation
  1070.         mov     al,trans.escchr         ; current escape char (port dependent)
  1071.         cmp     al,byte ptr keycode     ; is this Kermit's escape char?
  1072.         jne     dfkey2a                 ; ne = no
  1073.         test    keycode,scan            ; see if scan code
  1074.         jnz     dfkey2a                 ; nz = scan, so not ascii esc char
  1075.         mov     dx,offset dfkoops       ; Oops! msg
  1076.         mov     ah,prstr                ; complain and don't redefine
  1077.         int     dos
  1078.         stc                             ; failure
  1079.         ret
  1080.  
  1081. dfkey2a:push    di                      ; get a director code for this key
  1082.         push    cx      
  1083.         mov     di,offset keylist       ; list of keycodes
  1084.         mov     cx,nkeys                ; number currently defined
  1085.         mov     ax,keycode              ; present keycode
  1086.         jcxz    dfkey2b                 ; cx = 0 means none defined yet
  1087.         cld
  1088.         push    ds
  1089.         pop     es
  1090.         repne   scasw                   ; is current keycode in the list?
  1091.         jne     dfkey2b                 ; ne = not in list
  1092.         sub     di,2                    ; correct for auto increment
  1093.         sub     di,offset keylist
  1094.         mov     listptr,di              ; list pointer for existing definition
  1095.         pop     cx
  1096.         pop     di
  1097.         jmp     dfkey3                  ; go process definition
  1098.  
  1099. dfkey2b:pop     cx                      ; key not currently defined so
  1100.         pop     di                      ;  make a new director entry for it
  1101.         mov     bx,nkeys                ; number of keys previously defined
  1102.         cmp     bx,maxkeys              ; enough space?
  1103.         jae     dfkey2c                 ; ae = no, complain
  1104.         shl     bx,1                    ; count words
  1105.         mov     listptr,bx              ; index into word list
  1106.         mov     ax,keycode              ; get key's code
  1107.         mov     keylist[bx],ax          ; store it in list of keycodes
  1108.         mov     dirlist[bx],0           ; clear the new director entry
  1109.         inc     nkeys                   ; new number of keys
  1110.         jmp     dfkey3                  ; go process definition
  1111.  
  1112. dfkey2c:mov     dx,offset keyfull       ; say key space is full already
  1113.         mov     ah,prstr
  1114.         int     dos
  1115.         stc                             ; failure
  1116.         ret
  1117.  
  1118. ; listptr has element number in keylist or dirlist; keycode has key's code.
  1119.  
  1120. ; Parse new definition. First look for Kermit verbs as a line beginning
  1121. ; as \K or \{K. Otherwise, consider the line to be a string.
  1122. ; In any case, update the Director table for the new definition.
  1123.  
  1124. dfkey3: mov     brace,0                 ; assume not using braces
  1125.         mov     si,offset tranbuf       ; start of definition text
  1126.         cmp     byte ptr [si],'\'       ; starts with escape char?
  1127.         jne     dfkey5                  ; ne = no, so we have a string
  1128.         inc     si                      ; skip the backslash
  1129.         cmp     byte ptr [si],braceop   ; starts with \{?
  1130.         jne     dfkey3a                 ; ne = no
  1131.         inc     si                      ; skip the opening brace
  1132.         mov     brace,bracecl           ; expect closing brace
  1133. dfkey3a:cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  1134.         je      dfkey3b                 ; e = yes
  1135.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  1136.         jne     dfkey5                  ; ne = no, then it's a string
  1137. dfkey3b:inc     si                      ; yes, skip the K too
  1138.                                         ; Kermit action VERBS
  1139.         push    si                      ; save verb name start address
  1140. dfkey4: cld
  1141.         lodsb                           ; scan til closing brace or w/s or end
  1142.         or    al,al            ; premature end?
  1143.         jz      dfkey4b                 ; z = yes, accept without brace
  1144.         cmp     al,brace                ; closing brace?
  1145.         je      dfkey4b                 ; e = yes
  1146.         cmp     al,spc                  ; white space or control char?
  1147.         ja      short dfkey4            ; a = no, so not at end yet
  1148. dfkey4b:mov     byte ptr[si-1],0        ; insert null terminator
  1149.         pop     si                      ; recover start address
  1150.         call    tstkeyw                 ; find keyword, kw # returned in kbtemp
  1151.         jc      dfkey4d                 ; c = no keyword found, complain
  1152.         call    remstr                  ; clear old string, if string
  1153.         mov     ax,kbtemp               ; save keyword number
  1154.         and     ax,not(verb+strng)      ; clear verb / string field
  1155.         or      ax,verb                 ; set verb ident
  1156.         mov     si,listptr
  1157.         mov     dirlist[si],ax          ; store info in Director table
  1158.         jmp     dfkey7                  ; show results and return success
  1159.  
  1160. dfkey4d:mov     dx,offset verbbad       ; say no such verb
  1161.         mov     ah,prstr
  1162.         int     dos
  1163.         stc                             ; failure
  1164.         ret
  1165.  
  1166. ; Here we are left with the definition string; si points to its start, and
  1167. ; kbtemp holds its length (number of bytes). Null termination. If the string
  1168. ; begins with an opening brace it terminates on a matching closing brace
  1169. ; or the end of line, whichever occurs first. Trailing whitespace removed
  1170. ; before examining braces.
  1171. ; Null length strings mean define key as Self.
  1172.                                         ; STRING definitions
  1173. dfkey5: call    remstr                  ; first, clear old string, if any
  1174.         mov     si,offset tranbuf       ; si=source, di=dest, convert in-place
  1175.         mov     di,si
  1176.         call    cnvlin                  ; convert numbers, cx gets line length
  1177.         mov     si,offset tranbuf       ; provide address of new string
  1178.         cmp     cx,1                    ; just zero or one byte to do?
  1179.         jbe     dfkey6                  ; e = yes, do as a char
  1180.         call    insertst                ; insert new string, returns reg cx.
  1181.         jc      dfkey5h                 ; c = could not do insert
  1182.         mov     si,listptr              ; cx has type and string number
  1183.         mov     dirlist[si],cx          ; update Director table from insertst
  1184.         jmp     dfkey7                  ; show results and return success
  1185.  
  1186. dfkey5h:mov     dx,offset strbad        ; display complaint
  1187.         mov     ah,prstr
  1188.         int     dos
  1189.         stc                             ; failure
  1190.         ret
  1191.  
  1192.                 ; define SINGLE CHAR replacement or CLEAR a key definition.
  1193.                 ; cx has char count 1 (normal) or 0 (to undefine the key).
  1194. dfkey6: jcxz    dfkey6c                 ; z = cx= 0, clear definition
  1195.         mov     al,byte ptr [si]        ; get first byte from definition
  1196.         xor     ah,ah                   ; set the type bits to Char
  1197.         mov     si,listptr
  1198.         mov     dirlist[si],ax          ; store type and key's new code
  1199.         jmp     dfkey7                  ; return success
  1200.  
  1201. dfkey6c:push    si                      ; clear a definition,
  1202.         push    di                      ; listptr points to current def
  1203.         mov     si,listptr              ; starting address to clear
  1204.         add     si,offset dirlist
  1205.         mov     di,si                   ; destination
  1206.         add     si,2                    ; source is next word
  1207.         mov     cx,nkeys                ; current number of keys defined
  1208.         add     cx,cx                   ; double for listptr being words
  1209.         sub     cx,listptr              ; cx = number of words to move
  1210.         shr     cx,1                    ; convert to actual number of moves
  1211.         jcxz    dfkey6d                 ; z = none, just remove last word
  1212.         push    es
  1213.         push    ds
  1214.         pop     es                      ; make es:di point to data segment
  1215.         cld
  1216.         push    cx                      ; save cx
  1217.         rep     movsw                   ; move down higher list items
  1218.         pop     cx
  1219.         mov     si,listptr              ; do keylist too, same way
  1220.         add     si,offset keylist
  1221.         mov     di,si
  1222.         add     si,2
  1223.         rep     movsw
  1224.         pop     es
  1225. dfkey6d:mov     si,nkeys                ; clear old highest list element
  1226.         shl     si,1                    ; address words
  1227.         mov     dirlist[si],0           ; null the element
  1228.         mov     keylist[si],0           ; null the element
  1229.         dec     nkeys                   ; say one less key defined now
  1230.         pop     di                      ; restore saved registers
  1231.         pop     si
  1232.  
  1233. dfkey7: mov     ah,msutake              ; Finish up. In a Take file?
  1234.         or      ah,taklev               ; or even directly
  1235.         or    ah,ah
  1236.         jz    dfkey7a                 ; z = no
  1237.         cmp     flags.takflg,0          ; echo Take commands?
  1238.         je      dfkey7b                 ; e = no
  1239. dfkey7a:mov     ah,prstr                ; display cr/lf
  1240.         mov     dx,offset crlf
  1241.         int     dos
  1242.         call    shkey0                  ; show new definition (in SHKEY)
  1243.         call    shkfre                  ; show free string space
  1244. dfkey7b:clc                             ; return success
  1245.         ret
  1246. DFKEY   ENDP
  1247.  
  1248. ; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
  1249. ; command. Replaces obsolete procedure in msx---.
  1250. ; Prompts for a key and shows that key's (or all if ? entered) keycode,
  1251. ; definition, and the key definition free space remaining.
  1252.  
  1253. SHKEY   PROC    NEAR                    ; Show key's definition command
  1254.         mov     ah,cmeol                ; get a confirm
  1255.         call    comnd                   ; ignore any additional text
  1256.         push    bx
  1257.         mov     dx,offset shkmsg1       ; ask for original key
  1258.         mov     ah,prstr
  1259.         int     dos
  1260.         or      byte ptr kbcodes,80h    ; say kbcodes not-initiated
  1261. shky0:  call    getkey                  ; read keyboard, output to keycode
  1262.         jc      shky0                   ; wait for a key (c = nothing there)
  1263.         cmp     byte ptr keycode,'?'    ; query for all keys?
  1264.         jne     shky0a                  ; ne = no, not a query
  1265.         test    keycode,scan            ; is this a scan code, vs ascii query?
  1266.         jz      shky0c                  ; z = no Scan, so it is a query
  1267.  
  1268. shky0a: mov     ah,prstr                ; show single key. Setup display
  1269.         mov     dx,offset crlf
  1270.         int     dos
  1271.         call    shkey0                  ; show just one key
  1272. shky0b: call    shkfre                  ; show free string space
  1273.         jmp     shkeyx                  ; exit
  1274.  
  1275. shky0c: mov     cx,nkeys                ; Show all keys. nkeys = number defined
  1276.         jcxz    shky0b                  ; z = none to show
  1277.         mov     si,offset keylist       ; list of definitions
  1278.         push    si                      ; save pointer
  1279. shky1:  pop     si                      ; recover pointer
  1280.         cld
  1281.         lodsw                           ; get a keycode
  1282.         push    si                      ; save pointer
  1283.         push    cx                      ; save counter
  1284.         mov     keycode,ax              ; save new keycode
  1285.         mov     ah,prstr
  1286.         mov     dx,offset crlf
  1287.         int     dos
  1288.         call    shkey0                  ; show this keycode
  1289.  
  1290.         pop     cx                      ; pause between screens, recover cntr
  1291.         push    cx                      ; save it again
  1292.         dec     cx                      ; number yet to be shown
  1293.         jcxz    shky1b                  ; z = have now shown all of them
  1294.         mov     ax,nkeys                ; number of defined keys
  1295.         sub     ax,cx                   ; minus number yet to be displayed
  1296.         xor     dx,dx                   ; clear extended numerator
  1297.         div     twelve                  ; two lines per definition display
  1298.         or      dx,dx                   ; remainder zero (12 defs shown)?
  1299.         jnz     shky1b                  ; nz = no, not yet so keep going
  1300.         mov     ah,prstr
  1301.         mov     dx,offset shkmsg3       ; "push any key to continue" msg
  1302.         int     dos
  1303. shky1a:    mov    ah,0bh            ; check console, check ^C
  1304.     int    dos
  1305.     cmp    flags.cxzflg,'C'    ; a ^C?
  1306.     je    shky1b            ; e = yes, quit
  1307.     or    al,al
  1308.     jz    shky1a            ; z = nothing
  1309.     call    getkey            ; get any key
  1310.     jc    shky1a            ; c = nothing at keyboard yet, wait
  1311. shky1b:    pop    cx            ; resume loop
  1312.     cmp    flags.cxzflg,'C'    ; a ^C?
  1313.     je    shky1c            ; e = yes, quit
  1314.     loop    shky1
  1315. shky1c:    pop    si            ; clean stack
  1316.     call    shkfre            ; show free string space
  1317.     jmp    shkeyx            ; exit
  1318.  
  1319.                 ; show key worker routine, called from above
  1320.                                         ; SHKEY0 called by DFKEY just above
  1321. SHKEY0: test    keycode,scan            ; scan code?
  1322.         jz      shkey1                  ; z = no, regular ascii
  1323.  
  1324.                                         ; SCAN codes
  1325.         mov     dx,offset scanmsg       ; say Scan Code:
  1326.         mov     ah,prstr
  1327.         int     dos
  1328.         mov     ah,conout
  1329.         mov     dl,'\'                  ; add backslash before number
  1330.         int     dos
  1331.         mov     ax,keycode              ; get key's code again
  1332.         call    decout                  ; display 16 bit decimal keycode
  1333.         jmp     shkey2                  ; go get definition
  1334.  
  1335. shkey1: mov     dx,offset ascmsg        ; say ASCII CHAR
  1336.         mov     ah,prstr
  1337.         int     dos
  1338.         mov     dl,byte ptr keycode     ; get ascii code (al part of input)
  1339.         mov     ah,conout
  1340.         cmp     dl,spc                  ; control code?
  1341.         jae     shkey1a                 ; ae = no
  1342.         push    dx                      ; save char
  1343.         mov     dl,5eh                  ; show caret first
  1344.         int     dos
  1345.         pop     dx
  1346.         add     dl,'A'-1                ; ascii bias
  1347. shkey1a:cmp     dl,del                  ; DEL?
  1348.         jne     shkey1b                 ; ne = no
  1349.         mov     dl,'D'                  ; spell out DEL
  1350.         int     dos
  1351.         mov     dl,'E'
  1352.         int     dos
  1353.         mov     dl,'L'
  1354. shkey1b:int     dos
  1355.         mov     dl,spc                  ; add a couple of spaces
  1356.         int     dos
  1357.         int     dos
  1358.         mov     dl,'\'                  ; add backslash before number
  1359.         int     dos
  1360.         mov     ax,keycode              ; show 16 bit keycode in decimal
  1361.         call    decout                  ; and go get definiton
  1362.  
  1363.                                         ; Display defintion
  1364. shkey2: mov     dx,offset shkmsg2       ; intermediate part of reply
  1365.         mov     ah,prstr                ; " is defined as "
  1366.         int     dos
  1367.         push    di                      ; get a director code for this key
  1368.         push    cx      
  1369.         mov     di,offset keylist       ; list of keycodes
  1370.         mov     cx,nkeys                ; number currently defined
  1371.         jcxz    shkey2a                 ; z = none
  1372.         mov     ax,keycode              ; present keycode
  1373.         push    ds
  1374.         pop     es                      ; use data segment for es:di
  1375.         cld
  1376.         repne   scasw                   ; is current keycode in the list?
  1377.         jne     shkey2a                 ; ne = not in list
  1378.         sub     di,2                    ; correct for auto increment
  1379.         sub     di,offset keylist
  1380.         mov     listptr,di              ; list pointer for existing definition
  1381.         pop     cx
  1382.         pop     di
  1383.         jmp     shkey3                  ; go process definition
  1384.  
  1385. shkey2a:pop     cx
  1386.         pop     di
  1387.         mov     dx,offset noxmsg        ; say Self (no translation)
  1388.         mov     ah,prstr
  1389.         int     dos
  1390.         ret                             ; return to main show key loop
  1391.  
  1392. shkey3:                                 ; translations, get kind of.
  1393.         mov     si,listptr
  1394.         test    dirlist[si],verb        ; defined as verb?
  1395.         jnz     shkey6                  ; nz = yes, go do that one
  1396.         test    dirlist[si],strng       ; defined as string?
  1397.         jz      shkey3a                 ; z = no
  1398.         jmp     shkey8                  ; yes, do string display
  1399. shkey3a:
  1400.         mov     dx,offset ascmsg        ; CHAR. say 'Ascii char:'
  1401.         mov     ah,prstr
  1402.         int     dos
  1403.         mov     ax,dirlist [si]         ; get type and char
  1404.         mov     dl,al                   ; put char here for display
  1405.         push    ax                      ; save here too
  1406.         mov     ah,conout
  1407.         cmp     dl,spc                  ; control code?
  1408.         jae     shkey4                  ; ae = no
  1409.         push    dx
  1410.         mov     dl,5eh                  ; show caret
  1411.         int     dos
  1412.         pop     dx
  1413.         add     dl,'A'-1                ; add ascii bias
  1414. shkey4: cmp     dl,del                  ; DEL?
  1415.         jne     shkey4a                 ; ne = no
  1416.         mov     dl,'D'                  ; spell out DEL
  1417.         int     dos
  1418.         mov     dl,'E'
  1419.         int     dos
  1420.         mov     dl,'L'
  1421. shkey4a:int     dos
  1422.         mov     dl,spc                  ; add a couple of spaces
  1423.         mov     ah,conout
  1424.         int     dos
  1425.         int     dos
  1426.         mov     dl,'\'                  ; add backslash before number
  1427.         int     dos
  1428.         pop     ax                      ; recover char
  1429.         xor     ah,ah                   ; clear high byte
  1430.         call    decout                  ; show decimal value
  1431.         ret                             ; return to main show key loop
  1432.  
  1433. shkey6: mov     ah,prstr                ; VERB
  1434.         mov     dx,offset verbmsg       ; say 'verb'
  1435.         int     dos
  1436.         mov     si,listptr              ; get verb index from director
  1437.         mov     dx,dirlist[si]
  1438.         and     dx,not(verb+strng)      ; remove type bits, leaves verb number
  1439.         mov     bx,offset kverbs        ; table of verbs & actions
  1440.         mov     al,byte ptr [bx]        ; number of keywords
  1441.         xor     ah,ah
  1442.         dec     ax
  1443.         mov     kwcnt,ax                ; save number of last one here
  1444.         cmp     dx,ax                   ; asking for more than we have?
  1445.         ja      shkeyx                  ; a = yes, exit bad
  1446.         inc     bx                      ; point to first slot
  1447.         xor    cx,cx            ; current slot number
  1448. shkey6b:cmp     cx,dx                   ; this slot?
  1449.         je      shkey6c                 ; e = yes, print the text part
  1450.         ja      shkeyx                  ; a = beyond, exit bad
  1451.         mov     ax,[bx]                ; get cnt (keyword length)
  1452.         add     ax,4                    ; skip count and two byte value
  1453.         add     bx,ax                   ; bx = start of next keyword slot
  1454.         inc     cx                      ; current keyword number
  1455.         jmp     short shkey6b           ; try another
  1456. shkey6c:push    cx
  1457.     mov    cx,[bx]            ; length of definition
  1458.     add    bx,2            ; look at text field
  1459.     mov    di,bx            ; offset for printing
  1460.     call    prtscr            ; print counted string
  1461.     mov    ah,conout
  1462.     mov    dl,spc            ; add a couple of spaces
  1463.     int    dos
  1464.     int    dos
  1465.     mov    dl,'\'            ; show verb name as \Kverb
  1466.     int    dos
  1467.     mov    dl,'K'
  1468.     int    dos
  1469.     call    prtscr            ; print counted string, again
  1470.     pop    cx
  1471.     ret                ; return to main show key loop
  1472.  
  1473. shkey8: mov     ah,prstr                ; STRING
  1474.         mov     dx,offset strngmsg      ; say String:
  1475.         int     dos
  1476.         mov     si,listptr              ; get index from director
  1477.         mov     bx,dirlist[si]
  1478.         and     bx,not(verb+strng)      ; remove type bits
  1479.         shl     bx,1                    ; index words
  1480.         mov     si,sptable[bx]          ; table of string offsets
  1481.         mov     cx,word ptr [si]        ; get string length
  1482.         add     si,2            ; point to string text
  1483.         mov     ah,conout
  1484. shkey8a:cld
  1485.         lodsb                           ; get a byte
  1486.         cmp     al,spc                  ; control code?
  1487.         jae     shkey8b                 ; ae = no
  1488.         push    ax
  1489.         mov     dl,5eh                  ; show caret first
  1490.         int     dos
  1491.         pop     ax
  1492.         add     al,40h                  ; convert to printable for display
  1493. shkey8b:mov     dl,al
  1494.         int     dos                     ; display it
  1495.         loop    shkey8a                 ; do another
  1496.         ret                             ; return to main show key loop
  1497.         
  1498. shkeyx: pop     bx                      ; restore reg
  1499.         clc                             ; return success
  1500.         ret
  1501. SHKEY   ENDP
  1502.  
  1503. ;;;     keyboard translator local support procedures, system independent
  1504.  
  1505. ; Tstkeyw checks text word pointed to by si against table of keywords (pointed
  1506. ; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
  1507. ; Returns in kbtemp the number of the keyword and carry clear, or if failure
  1508. ; returns kbtemp zero and carry set.
  1509. ; Keyword structure is:         dw      cnt     (length of string 'word')
  1510. ;                               db      'word'  (keyword string)
  1511. ;                               dw      value   (value returned in bx)
  1512. ; Make these with macro mkeyw such as   mkeyw 'test',15   with the list of
  1513. ; such keywords headed by a byte giving the number of keywords in the list.
  1514. tstkeyw proc    near
  1515.         push    ax
  1516.         push    cx
  1517.         push    si
  1518.         mov     verblen,0               ; verblen will hold verb length
  1519.         push    si                      ; save user's verb pointer
  1520. tstkw1: cld
  1521.         lodsb                           ; get a verb character
  1522.         cmp     al,spc                  ; verbs are all non-spaces and above
  1523.         jbe     tstkw2                  ; be = done (space or control char)
  1524.         inc     verblen                 ; count verb length
  1525.         jmp     short tstkw1            ; printable char, look for more
  1526. tstkw2: pop     si                      ; pointer to verb
  1527.         mov     bx,offset kverbs        ; table of Kermit verb keywords
  1528.         mov     al,byte ptr [bx]        ; number of keywords
  1529.         xor     ah,ah
  1530.         mov     kwcnt,ax                ; save number of keywords here
  1531.         inc     bx                      ; point bx to first slot
  1532.         mov     kbtemp,0                ; remember which keyword
  1533.  
  1534. tstkw3:                                 ; match table keyword and text word
  1535.         mov     cx,verblen              ; length of user's verb
  1536.         cmp     [bx],cx                ; compare length vs table keyword
  1537.         jne     tstkw4                  ; ne = not equal lengths, try another
  1538.         push    si                      ; lengths match, how about spelling?
  1539.         push    bx
  1540.         add     bx,2            ; point at start of keyword
  1541. tstkw3a:mov     ah,byte ptr [bx]        ; keyword char
  1542.         mov     al,byte ptr [si]        ; text char
  1543.         cmp     ah,'A'
  1544.         jb      tstkw3b                 ; b = control chars
  1545.         cmp     ah,'Z'
  1546.         ja      tstkw3b                 ; a = not upper case alpha
  1547.         add     ah,'a'-'A'              ; convert upper case to lower case
  1548. tstkw3b:cmp     al,'A'
  1549.         jb      tstkw3c
  1550.         cmp     al,'Z'
  1551.         ja      tstkw3c
  1552.         add     al,'a'-'A'              ; convert upper case to lower case
  1553. tstkw3c:cmp     al,ah                   ; test characters
  1554.         jne     tstkw3d                 ; ne = no match
  1555.         inc     si                      ; move to next char
  1556.         inc     bx
  1557.         loop    tstkw3a                 ; loop through entire length
  1558. tstkw3d:pop     bx
  1559.         pop     si
  1560.         jcxz    tstkw5                  ; z: cx = 0, exit with match;
  1561.                                         ;  else select next keyword
  1562. tstkw4: inc     kbtemp                  ; number of keyword to test next
  1563.         mov     cx,kbtemp
  1564.         cmp     cx,kwcnt                ; all done? Recall kbtemp starts at 0
  1565.         jae     tstkwx                  ;ae = exhausted search, unsuccessfully
  1566.         mov     ax,[bx]            ; cnt (keyword length from macro)
  1567.         add     ax,4                    ; skip over count and two byte value
  1568.         add     bx,ax                   ; bx = start of next keyword slot
  1569.         jmp     tstkw3                  ; do another comparison
  1570.  
  1571. tstkw5:                                 ; get action pointer
  1572.         mov     ax,[bx]                ; cnt (keyword length from macro)
  1573.         add     ax,2                    ; skip over count
  1574.         add     bx,ax                   ; now bx points to dispatch value
  1575.         mov     bx,[bx]                 ; bx holds dispatch value
  1576.         clc                             ; carry clear for success
  1577.         jmp     short tstkwxx           ; exit
  1578.         ret
  1579. tstkwx: xor     bx,bx                   ; exit when no match
  1580.         mov     kbtemp,bx               ; make verb number be zero too
  1581.         stc                             ; carry set for failure
  1582. tstkwxx:pop     si
  1583.         pop     cx
  1584.         pop     ax
  1585.         ret
  1586. tstkeyw endp
  1587.  
  1588. ; Insert asciiz string pointed to by si into string buffer stbuf.
  1589. ; Reg cx has string length upon entry.
  1590. ; Success: returns offset of first free byte (strmax) in string buffer stbuf,
  1591. ; cx = type and Index of new string, and carry clear.
  1592. ; Failure = carry set.
  1593. insertst proc   near
  1594.         push    bx
  1595.         push    dx
  1596.         push    si
  1597.         push    di
  1598.         push    kbtemp          ; save this variable too
  1599.         mov     dx,cx           ; save length of incoming string in dx
  1600.         mov     bx,offset sptable ; table of string offsets
  1601.         mov     kbtemp,0        ; slot number
  1602.         mov     cx,maxstng      ; number of entries, find an empty slot
  1603. insert1:cmp     word ptr[bx],0  ; slot empty?
  1604.         je      insert2         ; e = yes
  1605.         inc     kbtemp          ; remember slot number
  1606.         add     bx,2            ; look at next slot
  1607.         loop    insert1         ; keep looking
  1608.         jmp     short insert4   ; get here if no empty slots
  1609. insert2:                        ; see if stbuf has sufficient space
  1610.         mov     cx,dx           ; length of new string to cx
  1611.         mov     di,strmax       ; offset of first free byte in stbuf
  1612.         add     di,cx           ; di = address where this string would end
  1613.         cmp     di,offset stbuf+stbuflen ; beyond end of buffer?
  1614.         jae     insert4         ; ae = yes, not enough room
  1615.         mov     di,strmax       ; point to first free slot in stbuf
  1616.         mov     [bx],di         ; fill slot with address offset of buffer
  1617.         push    es
  1618.         push    ds
  1619.         pop     es              ; point es:di to data segment
  1620.         cld
  1621.         mov     [di],cx     ; length of text for new string
  1622.         add     di,2        ; move to next storage slot
  1623.         rep     movsb           ; copy string text
  1624.         pop     es
  1625.         mov     strmax,di       ; offset of next free byte
  1626.         mov     cx,kbtemp       ; return new slot number with Director Index
  1627.         and     cx,not(strng+verb) ; clear type bits
  1628.         or      cx,strng        ; say type is multi-char string
  1629.         clc                     ; say success
  1630.         jmp     short insertx   ; exit
  1631. insert4:stc                     ; say no-can-do
  1632. insertx:pop     kbtemp
  1633.         pop     di
  1634.         pop     si
  1635.         pop     dx
  1636.         pop     bx
  1637.         ret
  1638. insertst endp
  1639.  
  1640. ; Remove (delete) string. Enter with listptr preset for director entry.
  1641. ; Acts only on existing multi-char strings; recovers freed space.
  1642. ; All registers preserved.
  1643. remstr  proc    near            
  1644.         push    si
  1645.         mov     si,listptr              ; list pointer
  1646.         test    dirlist[si],strng       ; multi-char string?
  1647.         pop     si
  1648.         jnz     remst1                  ; nz = a multi-char string
  1649.         ret                             ; else do nothing
  1650. remst1: push    ax
  1651.         push    bx
  1652.         push    cx
  1653.         push    dx
  1654.         push    si
  1655.         mov     si,listptr
  1656.         mov     ax,dirlist[si]          ; Director table entry
  1657.         and     ax,not(strng+verb) ; clear type bits, leave string's pointer
  1658.         mov     dirlist[si],0           ; clear Director table entry
  1659.         shl     ax,1                    ; index words not bytes
  1660.         mov     si,offset sptable       ; list of string offsets in stbuf
  1661.         add     si,ax                   ; plus index = current slot
  1662.         mov     bx,[si]                 ; get offset of string to be deleted
  1663.         mov     dx,bx                   ; save in dx for later
  1664.         mov     cx,[bx]                ; get length of subject string
  1665.         add     cx,2            ; length word too, cx has whole length
  1666.         sub     strmax,cx       ; count space to be freed (adj end-of-buf ptr)
  1667.         mov     word ptr [si],0 ; clear sptable of subject string address
  1668.         push    cx                      ; save length of purged string
  1669.         push    di                      ; save di
  1670.         push    si
  1671.         push    es                      ; save es
  1672.         push    ds
  1673.         pop     es              ; setup es:di to be ds:offset of string
  1674.         mov     di,dx           ; destination = start address of purged string
  1675.         mov     si,dx           ; source = start address of purged string
  1676.         add     si,cx           ;  plus string length of purged string.
  1677.         mov     cx,offset stbuf+stbuflen ; 1 + address of buffer end
  1678.         sub     cx,si                   ; 1 + number of bytes to move
  1679.         dec     cx                      ; number of bytes to move
  1680.         jcxz    remst2                  ; z = none
  1681.         cld                             ; direction is forward
  1682.         rep     movsb                   ; move down preserved strings
  1683. remst2: pop     es                      ; restore regs
  1684.         pop     di
  1685.         pop     si
  1686.         pop     ax              ; recover length of purged string (was in cx)
  1687.         mov     bx,offset sptable       ; string pointer table
  1688.         mov     cx,maxstng              ; max mumber of entries
  1689. remst4: cmp     [bx],dx         ; does this entry occur before purged string?
  1690.         jbe     remst5          ; be = before or equal, so leave it alone
  1691.         sub     [bx],ax         ; recompute address (remove old string space)
  1692. remst5: add     bx,2                    ; look at next list entry
  1693.         loop    remst4                  ; do all entries in sptable
  1694.         pop     si
  1695.         pop     dx
  1696.         pop     cx
  1697.         pop     bx
  1698.         pop     ax
  1699.         ret
  1700. remstr  endp
  1701.  
  1702. shkfre  proc    near                    ; show free key & string defs & space
  1703.         push    ax                      ; preserves all registers.
  1704.         push    bx
  1705.         push    cx
  1706.         push    dx
  1707.         push    kbtemp
  1708.         mov     dx,offset fremsg
  1709.         mov     ah,prstr
  1710.         int     dos
  1711.         mov     ax,maxkeys              ; max number of key defs
  1712.         sub     ax,nkeys                ; number currently used
  1713.         call    decout                  ; show the value
  1714.         mov     ah,prstr
  1715.         mov     dx,offset kyfrdef       ; give key defs msg
  1716.         int     dos
  1717.         mov     bx,offset sptable       ; table of string pointers
  1718.         mov     cx,maxstng              ; number of pointers
  1719.         mov     kbtemp,0                ; number free
  1720. shkfr1: cmp     word ptr [bx],0         ; slot empty?
  1721.         jne     shkfr2                  ; ne = no
  1722.         inc     kbtemp                  ; count free defs
  1723. shkfr2: add     bx,2                    ; look at next slot
  1724.         loop    shkfr1                  ; do all of them
  1725.         mov     ax,kbtemp               ; number of free defs
  1726.         call    decout                  ; display
  1727.         mov     dx,offset stfrdef       ; say free string defs
  1728.         mov     ah,prstr
  1729.         int     dos
  1730.         mov     ax,offset stbuf+stbuflen+1 ; 1 + last byte in stbuf
  1731.         sub     ax,strmax               ; offset of last free byte in stbuf
  1732.         call    decout
  1733.         mov     dx,offset stfrspc       ; give free space part of msg
  1734.         mov     ah,prstr
  1735.         int     dos
  1736.         pop     kbtemp
  1737.         pop     dx
  1738.         pop     cx
  1739.         pop     bx
  1740.         pop     ax
  1741.         ret
  1742. shkfre  endp
  1743.  
  1744. ; Initialize the keyboard tables at Kermit startup time. Optional procedure.
  1745. ; Requires kbdinlst to be configured with mkeyw macro in the form
  1746. ;       mkeyw   'definition',keytype*256+keycode
  1747. ; keytype is 0 for scan codes and non-zero for ascii.
  1748. ; Returns normally.
  1749. kbdinit proc    near                    ; read keyword kbdinlst and setup
  1750.         or      byte ptr kbcodes,80h    ; say kbcodes not-initiated
  1751.         push    ds                      ;  initial keyboard assignments.
  1752.         pop     es                      ; set es:di to data segment
  1753.         inc     taklev                  ; pretend that we are in Take file
  1754. kbdini0:mov     si,offset kbdinlst      ; start of list of definitions
  1755. kbdini1:mov     cx,[si]            ; cnt field (keyword length of macro)
  1756.         jcxz    kbdinix                 ; z = null cnt field = end of list
  1757.         add     si,2            ; look at text field
  1758.         mov     di,offset tranbuf       ; where defkey expects text
  1759.         cld
  1760.         rep     movsb                   ; copy cx chars to tranbuf
  1761.         mov     byte ptr [di],0         ; insert null terminator
  1762.         mov     ax,word ptr [si]        ; get value field
  1763.         mov     keycode,ax              ; set key ident value
  1764.     push    si
  1765.         call    dfkey2                  ; put dfkey to work
  1766.         pop     si
  1767.         add     si,2                    ; point to next entry
  1768.         jmp     kbdini1                 ; keep working
  1769. kbdinix:dec     taklev                  ; reset Take file level
  1770.         call    udkclear                ; clear User Definable Keys
  1771.         ret
  1772. kbdinit endp
  1773. ;;;     End of System Independent Procedures
  1774.  
  1775. ;;;     Begin System Dependent Procedures
  1776.  
  1777. ; Read keyboard. System dependent.
  1778. ; Return carry set if nothing at keyboard.
  1779. ; If char present return carry clear with key's code in Keycode.
  1780. ; If key is ascii put that in the low byte of Keycode and clear bit Scan in
  1781. ; the high byte; otherwise, put the scan code in the lower byte and set bit
  1782. ; Scan in the high byte.  Uses dos keyboard reading.
  1783. ; Modifies register ax.
  1784. getkey  proc    near
  1785.         mov     keycode,0               ; clear old keycode
  1786.         cmp     dosflg,0                ; do ascii keyboard reading?
  1787.         jnz     getky7                  ; nz = yes, ascii
  1788.         jmp     getky6                  ; do scan code form
  1789.                                         ; ;;;;;;;; A S C I I ;;;;;;;;;
  1790. getky7: test    dosflg1,1               ; scan codes enabled?
  1791.         jz      getky7a                 ; z = no, continue
  1792.         call    dis_scan                ; disable them
  1793. getky7a:test    byte ptr kbcodes,80h    ; kbcodes initiated?            [dan]
  1794.         jz      getky5                  ; z = yes                       [dan]
  1795.         push    si
  1796.         call    nrc2cp                  ; point SI at this code page to NRC
  1797.         mov     nrcptr,si
  1798.         pop     si
  1799.         push    bx
  1800.         call    cplatin                 ; code page to Latin1, BX gets ptr
  1801.         mov     latinptr,bx
  1802.         call    cpdecsg                 ; code page to DEC-MCS, BX gets ptr
  1803.         mov     decmnptr,bx
  1804.         pop     bx
  1805.         and     byte ptr kbcodes,not 80h ; say kbcodes initiated
  1806. getky5: call    iseof                   ; is stdin at eof?
  1807.         jnc     getky5k                 ; nc = not eof, get more
  1808.         mov     al,trans.escchr         ; Kermit's escape char
  1809.         mov     byte ptr keycode,al     ; save ascii char
  1810.         clc                             ;  to get out gracefully at EOF
  1811.         ret                             ; and exit
  1812.  
  1813. getky5k:push    dx
  1814.         mov     dl,0ffh                 ; DOS read operation
  1815.         mov     ah,dconio               ; from stdin
  1816.         int     dos
  1817.         pop     dx
  1818.         jnz     getky5a                 ; nz = char available
  1819.         stc                             ; carry set = nothing available
  1820.         ret                             ; exit on no char
  1821. getky5a:xor     ah,ah
  1822.         cmp     al,16                   ; Control P?
  1823.         jne     getky5b                 ; ne = no
  1824.         mov     al,0a2h                 ; force F12 scan code, put on printer
  1825.         or      keycode,scan            ; ensure scan bit is set
  1826.         jmp     short getky5c
  1827. getky5b:cmp     al,BS                   ; backspace key?
  1828.         jne     getky5c                 ; ne = no
  1829. ;       or      keycode,scan            ; ensure scan bit is set
  1830. getky5c:mov     byte ptr keycode,al     ; save ascii char
  1831.         clc                             ; carry clear = got a char
  1832.         ret                             ; and exit
  1833.                                         ; ;;;;;; S C A N C O D E ;;;;;;
  1834. getky6: test    dosflg1,1               ; scan codes enabled?
  1835.         jnz     getky6a                 ; nz = yes, continue
  1836.         call    ena_scan                ; enable them
  1837. getky6a:test    byte ptr kbcodes,80h    ; kbcodes initiated?            [dan]
  1838.         jz      getky6b                 ; z = yes                       [dan]
  1839.         mov     kbcodes,0001h           ; low byte = status, high = read char
  1840.         push    si
  1841.         call    nrc2cp                  ; point SI at this code page to NRC
  1842.         mov     nrcptr,si
  1843.         pop     si
  1844.         push    bx
  1845.         call    cplatin                 ; code page to Latin1, BX gets ptr
  1846.         mov     latinptr,bx
  1847.         call    cpdecsg                 ; code page to DEC-MCS, BX gets ptr
  1848.         mov     decmnptr,bx
  1849.         pop     bx
  1850. getky6b:call    iseof                   ; is stdin at eof?
  1851.         jnc     getky6c                 ; nc = not eof, get more
  1852.         mov     al,trans.escchr         ; Kermit's escape char
  1853.         mov     byte ptr keycode,al     ; save ascii char
  1854.         clc                             ;  to get out gracefully at EOF
  1855.         ret                             ; and exit
  1856. getky6c:push    dx
  1857.         mov     dl,0ffh                 ; DOS read operation
  1858.         mov     ah,dconio               ; from stdin
  1859.         int     dos
  1860.         pop     dx
  1861.         jnz     getky6d                 ; nz = char available
  1862.         stc                             ; carry set = nothing available
  1863.         ret                             ; exit on no char
  1864. getky6d:call    fixflg                  ; go set keycode flags in ax
  1865.         cmp     al,80h                  ; start of special keys
  1866.         jb      getky6g                 ; go make these pure ascii
  1867. getky6e:or      ax,scan                 ; set the scan bit
  1868. getky6f:mov     keycode,ax
  1869.         clc
  1870.         ret
  1871. getky6g:push    cx
  1872.         mov     cx,shift
  1873.         or      cx,control
  1874.         not     cx
  1875.         and     ax,cx                   ; clear shift and control bits
  1876.         pop     cx
  1877.         jmp     short getky6f
  1878. getkey  endp
  1879.  
  1880. ; Return modified char code, depending on SET TERM CHAR-SET and active
  1881. ; Code Page. Enter and exit with char in AL.
  1882. xltkey  proc    near
  1883.     cmp    al,' '            ; control character?
  1884.     jb    xltkey2            ; b = yes, do not translate
  1885.         cmp     flags.xltkbd,0          ; keyboard translation is off?
  1886.         je      xltkey2                 ; e = yes
  1887.         cmp     vtemu.vtchset,0         ; NRC's, using ASCII already?
  1888.         je      xltkey2                 ; e = yes, use char in AL
  1889.         cmp     vtemu.vtchset,12        ; 1-12 for NCRs?
  1890.         ja      xltkey3                 ; a = no
  1891.         push    si
  1892.         push    di
  1893.         push    ax
  1894.         mov     si,nrcptr               ; point SI at this code page to NRC
  1895.         pop     ax
  1896.         mov     di,si                   ; start of table are ASCII chars
  1897.         mov     cl,vtemu.vtchset        ; get set number (1-12)
  1898.         xor     ch,ch
  1899.         sub     di,cx                   ; minus one byte per set
  1900.         shl     cx,1                    ; 15 bytes per NRC entry
  1901.         shl     cx,1
  1902.         shl     cx,1
  1903.         shl     cx,1
  1904.         add     di,cx                   ; +16, source, point at this entry
  1905.         mov     cx,12                   ; do first 12 bytes of them
  1906.         push    es
  1907.         push    ds
  1908.         pop     es
  1909.         cld
  1910.         repne   scasb                   ; look for this byte code in table
  1911.         pop     es
  1912.         jne     xltkey1                 ; ne = not found, use char in AL
  1913.         inc     cx
  1914.         sub     cx,12                   ; compute char index
  1915.         neg     cx
  1916.         add     si,cx                   ; index into ASCII table
  1917.         mov     al,[si]                 ; get matching ASCII char (set 0)
  1918. xltkey1:pop     di
  1919.         pop     si
  1920. xltkey2:ret
  1921.                                         ; LATIN1 set
  1922. xltkey3:test    al,80h                  ; high bit set?
  1923.         jz      xltkey2                 ; z = no, no translation
  1924.         cmp     vtemu.vtchset,15        ; set term character-set LATIN1?
  1925.         jne     xltkey4                 ; ne = no
  1926.         and     al,not 80h              ; remove high bit
  1927.         push    bx
  1928.         mov     bx,latinptr             ; Code Page to Latin1
  1929.         xlatb                           ; translate to Latin1 in AL
  1930.         pop     bx
  1931.         ret
  1932. xltkey4:cmp     vtemu.vtchset,16        ; set term character-set DEC-MCS?
  1933.         jne     xltkey2                 ; ne = no
  1934.         and     al,not 80h              ; remove high bit
  1935.         push    bx
  1936.         mov     bx,DECmnptr             ; Code Page to DEC-MCS
  1937.         xlatb                           ; translate to DEC-MCS in AL
  1938.         pop     bx
  1939.         ret
  1940. xltkey  endp
  1941.  
  1942.  
  1943. ; Do any local processing after reading a key during active translation
  1944. ; Avoids same actions if a key is being defined or shown.
  1945. postkey proc    near
  1946.                                         ; Key Click code for VT102 emulator
  1947.         cmp     flags.vtflg,0           ; emulating? (0 = no)
  1948.         je      postke1                 ; e = extra clicks not available
  1949.         test    vtemu.vtflgst,vskeyclick ; flags from SET TERM
  1950.         jz      postke1                 ; z = extra clicks not wanted
  1951.         call    vclick                  ; click, what else?
  1952. postke1:ret
  1953. postkey endp
  1954.  
  1955. ;keycom sends commands in dl to the Z-100 keyboard processor
  1956. keycom  proc    near
  1957.         in      al,keystat              ; check status
  1958.         test    al,KPR                  ; keyboard ready?
  1959.         jnz     keycom                  ; keep trying if not ready
  1960.         mov     al,dl                   ; we need command here
  1961.         out     keycmd,al               ; do it
  1962.         ret
  1963. keycom  endp
  1964.  
  1965. ;fixflg updates ax by seting the proper shift keycode flags in ah
  1966. ;enter with true Z-100 ascii scan code in al
  1967. ;returns with ax updated per keycode standards, except bit scan not set  
  1968. fixflg  proc    near
  1969.         xor     ah,ah                   ; we need it clean
  1970.         push    di                      ; search list z10keyl for this keycode
  1971.         push    cx                      ; save some registers   
  1972.         push    es
  1973.         mov     di,offset z10keyl       ; list of defined keycode bytes
  1974.         mov     cx,lz10keyl             ; number of bytes to examine
  1975.         push    ds
  1976.         pop     es                      ; make es:di point to data segment
  1977.         cld
  1978.         repne   scasb                   ; find keycode in list
  1979.         pop     es                      ; restore regs
  1980.         je      fixflg1                 ; e = found, work with present di
  1981.         pop     cx                      ; restore original cx
  1982.         pop     di                      ; restore original di
  1983.         ret                             ; char is already in al
  1984. fixflg1:neg     cx                      ; subtract cx from
  1985.         add     cx,lz10keyl             ; we went this far into the table
  1986.         and     cx,3                    ; we need these bits
  1987.         cmp     cx,1                    ; nothing?
  1988.         jz      fixflg4                 ; done
  1989.         cmp     cx,2                    ; shift?
  1990.         jnz     fixflg2                 ; no, go check control
  1991.         or      ax,shift                ; shift, set 200
  1992.         jmp     fixflg4                 ; done
  1993. fixflg2:cmp     cx,3                    ; control?
  1994.         jnz     fixflg3                 ; no, jump
  1995.         or      ax,control              ; yes, control, set 400
  1996.         jmp     fixflg4                 ; done
  1997. fixflg3:or      ax,shift                ; must be
  1998.         or      ax,control              ;  both of these
  1999. fixflg4:pop     cx
  2000.         pop     di
  2001.         ret
  2002. fixflg  endp
  2003.  
  2004. code    ends
  2005.         end
  2006.