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

  1.         NAME    msuap3
  2. ; File MSUAP3.ASM
  3. ; Keyboard translator, by Joe R. Doupnik, Dec 1986
  4. ;  with contributions from David L. Knoell.
  5. ; For NEC APC III by RFGoeke
  6. ; edit history:
  7. ; Last edit: 14 March 1988
  8. ; 14 Mar 1988: Incorporated msuibm mods for v2.30 released 1 Jan 1988 
  9. ; 4 Dec 1987: (added aliases for keypad keys -- RFG)
  10.  
  11.         include mssdef.h
  12.  
  13.         public  keybd, dfkey, shkey, msuinit
  14.  
  15. ; some definitions
  16. kbint   equ     18h                     ; NEC, Bios keyboard interrupt
  17. shift   equ     200h                    ; IBM, synonym for right or left shift
  18. control equ     400h                    ; IBM, synonym for control shift
  19.  
  20. maxkeys equ     128                     ; maximum number of key definitions
  21. maxstng equ     64                      ; maximum number of multi-char strings
  22. stbuflen equ    1000                    ; length of string buffer (bytes)
  23.  
  24. verb    equ     8000h                   ; dirlist flag: use verb action table
  25. strng   equ     4000h                   ; dirlist flag: use string action table
  26. scan    equ     100h                    ; keycode flag: code is scan not ascii
  27. braceop equ     7bh                     ; opening curly brace
  28. bracecl equ     7dh                     ; closing curly brace
  29.  
  30. datas   segment public 'datas'
  31.         extrn taklev:byte, comand:byte, intake:byte, flags:byte
  32.         extrn shkadr:word, stkadr:word, trans:byte
  33.                                                 ; system dependent references
  34.         extrn vtemu:byte                        ; emulator data [jrd]
  35.  
  36. ;;;     System Independent local storage
  37.  
  38. tranbuf db      132 dup (?)             ; 132 byte translator work buffer
  39. crlf    db      cr,lf,'$'
  40. dfhelp1 db    cr,lf,' Enter key',27h,'s identification as a character',cr,lf
  41.         db      '  or as its numerical equivalent \{b##} of ascii',cr,lf
  42.         db      '  or as its scan code \{b##}'
  43.         db      cr,lf,'  or as SCAN followed by its scan code',cr,lf
  44.         db      '    where b is O for octal, X for hex, or D for decimal'
  45.         db      ' (default).',cr,lf,'    Braces {} are optional.'
  46.         db      cr,lf,'    Follow the identification with the new definition.'
  47.         db      cr,lf,' or CLEAR to restore initial key settings.$'  ;APCIII
  48. ;        db      cr,lf,' or ON (def) for Bios i/o or OFF to use DOS i/o.$' ;IBM
  49. dfaskky db      cr,lf,' Push key to be defined: $'
  50. dfaskdf db      ' Enter new definition: $'
  51. verbbad db      cr,lf,' No such verb',cr,lf,'$'
  52. strbad  db      cr,lf,' Not enough space for new string',cr,lf,'$'
  53. keyfull db      cr,lf,' No more space to define keys',cr,lf,'$'
  54. dfkopps db      cr,lf,' Opps! That is Kermit',27h,'s Escape Char.'
  55.         db      ' Translation is not permitted.',cr,lf,'$'
  56. shkmsg1 db      cr,lf,'Push key to be shown (? shows all): $'
  57. shkmsg2 db      ' decimal is defined as',cr,lf,'$'
  58. shkmsg3 db      cr,lf,'... more, push any key to continue ...$'
  59. kwarnmsg db     cr,lf,' Notice: this form of Set Key is obsolete$'
  60.  
  61. ascmsg  db      ' Ascii char: $'
  62. scanmsg db      ' Scan Code $'
  63. strngmsg db     ' String: $'
  64. verbmsg db      ' Verb: $'
  65. noxmsg  db      ' Self, no translation.$'
  66. fremsg  db      cr,lf,' Free space: $'
  67. kyfrdef db      ' key and $'
  68. stfrdef db      ' string definitions, $'
  69. stfrspc db      ' string characters.',cr,lf,'$'
  70.                                         ; translation tables
  71. keylist dw      maxkeys dup (0)         ; 16 bit keycodes, paralled by dirlist
  72. dirlist dw      maxkeys dup (0)         ; director {v+s} + {index | new char}
  73. sptable dw      maxstng dup (0)         ; list of asciiz string offsets
  74. stbuf   dw      stbuflen dup (0)        ; buffer for strings
  75. strmax  dw      stbuf                   ; first free byte in stbuf
  76. listptr dw      ?                       ; item number for keylist and dirlist
  77. nkeys   dw      0                       ; number of actively defined keys
  78. keycode dw      ?                       ; ascii/scan code for key
  79. kbtemp  dw      ?                       ; scratch storage for translator
  80. brace   db      ?                       ; brace detected flag byte
  81. oldform db      0                       ; old form Set Key, if non-zero
  82. verblen dw      ?                       ; length of user's verb (work temp)
  83. kwcnt   dw      ?                       ; number of keywords (work temp)
  84. msutake db      ?                       ; if being run from take file or not
  85. twelve  dw      12d
  86. dosflg  db      0
  87.  
  88. ;;;     End System Independent Data Area
  89.  
  90. ;;;     System Dependent Data Area
  91. ;       edit dfhelp2 to include nice list of verbs for this system.
  92. dfhelp2 db      cr,lf,' Enter either  \Kverb  for a Kermit action verb',cr,lf
  93.         db      ' or a replacement string  (single byte binary numbers are'
  94.         db      ' \{b##})',cr,lf,' or push Return to undefine a key, ^C to'
  95.         db      ' retain current definition.'
  96.         db      cr,lf,' Braces {} are optional, and strings maybe enclosed in'
  97.         db      ' them.',cr,lf,' Strings may not begin with the character'
  98.         db      ' combinations of  \k  or  \{k',cr,lf
  99.         db      '    (start with a { brace instead).',cr,lf,lf
  100.         db      ' Verbs are as follows. VT102 keys (arrows and keypad):',cr,lf
  101.         db   '   uparr, dnarr, lfarr, rtarr, kpminus, kpcoma, kpdot, kpenter,'
  102.         db      cr,lf
  103.         db   '   Gold (same as PF1), PF1, PF2, PF3, PF4, kp0, ... kp9'
  104.         db      cr,lf,' Kermit screen control and actions:',cr,lf
  105.         db   '   upscn, dnscn, homscn, endscn, upone, dnone, prtscn, dump,'
  106.         db      cr,lf
  107.         db   '   logoff, logon, termtype, reset, modeline, break, lbreak,'
  108.         db      cr,lf
  109.         db   '   hangup, null (send one), DOS, help, status, exit'
  110.         db      cr,lf,'$'
  111.  
  112.         ; Aliaskey: keys having aliases - same ascii code but more than one
  113.         ; scan code, as on auxillary keypads. Use just scan codes with these.
  114.         ; Alternative use: force ascii keys to report out just scan codes.
  115.         ; Table format: high byte = scan code, low byte = ascii code.
  116.         ; Contents are machine dependent.
  117. aliaskey equ    This Byte
  118.         dw      (0Eh*scan)+bs           ; Backspace key [hi=scan, lo=ascii]
  119.         dw      (1Dh*scan)+'^'          ; Second row right, hat key
  120.         dw      (3Eh*scan)+'/'          ; Grey / key
  121.         dw      (3Fh*scan)+'*'          ; keypad asterisk
  122.         dw      (40h*scan)+'7'          ; keypad
  123.         dw      (41h*scan)+'8'          ; keypad
  124.         dw      (42h*scan)+'9'          ; keypad
  125.         dw      (43h*scan)+'-'          ; keypad minus
  126.         dw      (44h*scan)+'4'          ; keypad
  127.         dw      (45h*scan)+'5'          ; keypad
  128.         dw      (46h*scan)+'6'          ; keypad
  129.         dw      (47h*scan)+'+'          ; keypad plus
  130.     dw      (48h*scan)+'1'          ; keypad
  131.         dw      (49h*scan)+'2'          ; keypad
  132.         dw      (4Ah*scan)+'3'          ; keypad
  133.         dw      (4Bh*scan)+0Dh          ; keypad Enter
  134.         dw      (4Ch*scan)+'0'          ; keypad
  135.         dw      (4Dh*scan)+'.'          ; keypad period
  136. aliaslen equ    ($-aliaskey) shr 1      ; number of words in aliaskey table
  137.  
  138. kverbs  db      45                      ; number of table entries below
  139.         mkeyw   'uparr',uparrw          ; independent of ordering and case!
  140.         mkeyw   'dnarr',dnarrw          ; mkeyw 'name',procedure entry point
  141.         mkeyw   'lfarr',lfarr
  142.         mkeyw   'rtarr',rtarr
  143.         mkeyw   'gold',pf1
  144.         mkeyw   'pf1',pf1
  145.         mkeyw   'pf2',pf2
  146.         mkeyw   'pf3',pf3
  147.         mkeyw   'pf4',pf4
  148.         mkeyw   'kp0',kp0
  149.         mkeyw   'kp1',kp1
  150.         mkeyw   'kp2',kp2
  151.         mkeyw   'kp3',kp3
  152.         mkeyw   'kp4',kp4
  153.         mkeyw   'kp5',kp5
  154.         mkeyw   'kp6',kp6
  155.         mkeyw   'kp7',kp7
  156.         mkeyw   'kp8',kp8
  157.         mkeyw   'kp9',kp9
  158.         mkeyw   'kpminus',kpminus
  159.         mkeyw   'kpcoma',kpcoma
  160.         mkeyw   'kpenter',kpenter
  161.         mkeyw   'kpdot',kpdot
  162.         mkeyw   'termtype',vtans52
  163.         mkeyw   'reset',vtinit
  164.         mkeyw   'dnscn',dnwpg
  165.         mkeyw   'upscn',upwpg
  166.         mkeyw   'endscn',endwnd
  167.         mkeyw   'homscn',homwnd
  168.         mkeyw   'upone',upone
  169.         mkeyw   'dnone',dnone
  170.         mkeyw   'prtscn',trnprs
  171.         mkeyw   'dump',dmpscn
  172.         mkeyw   'modeline',trnmod
  173.         mkeyw   'break',sendbr
  174.         mkeyw   'lbreak',sendbl
  175.         mkeyw   'hangup',chang
  176.         mkeyw   'null',snull
  177.         mkeyw   'logon',klogon
  178.         mkeyw   'logoff',klogof
  179.         mkeyw   'DOS',cdos
  180.         mkeyw   'help',cquery
  181.         mkeyw   'status',cstatus
  182.         mkeyw   'exit',cquit
  183.  
  184.         ; Initialization data. Overlay kbdinlst on stbuf for Kermit startup
  185. loccount equ    $               ; remember current location counter here
  186.         ORG     offset stbuf+2  ; assemble at offset stbuf+2, watch length!
  187. kbdinlst equ    this byte     ; Kermit NEC initialization time keyboard setup
  188.         mkeyw   '\kgold',scan+62h       ; F1    mkeyw 'definition',keycode
  189.         mkeyw   '\kpf2',scan+63h        ; F2
  190.         mkeyw   '\kpf3',scan+64h        ; F3
  191.         mkeyw   '\kpf4',scan+65h        ; F4
  192.         mkeyw   '\kkp0',scan+92h        ; VT100 keypad numeric area, SF7
  193.         mkeyw   '\kkp1',scan+8eh        ; SF3
  194.         mkeyw   '\kkp2',scan+8fh        ; SF4
  195.         mkeyw   '\kkp3',scan+90h        ; SF5
  196.         mkeyw   '\kkp4',scan+6ah        ; F9
  197.         mkeyw   '\kkp5',scan+6bh        ; F10
  198.         mkeyw   '\kkp6',scan+8ch        ; SF1
  199.         mkeyw   '\kkp7',scan+66h        ; F5
  200.         mkeyw   '\kkp8',scan+67h        ; F6
  201.         mkeyw   '\kkp9',scan+68h        ; F7
  202.         mkeyw   '\kkpenter',scan+91h    ; SF6
  203.         mkeyw   '\kkpcoma',scan+8dh     ; SF2
  204.         mkeyw   '\kkpminus',scan+69h    ; F8
  205.         mkeyw   '\kkpdot',scan+93h      ; SF8
  206.         mkeyw   '\kuparr',scan+39h      ; VT100 cursor keys (arrows)
  207.         mkeyw   '\kdnarr',scan+3ch
  208.         mkeyw   '\klfarr',scan+3ah
  209.         mkeyw   '\krtarr',scan+3bh
  210.         mkeyw   '\kupscn',scan+35h     ; PgUp  Kermit screen roll back keys
  211.         mkeyw   '\kdnscn',scan+36h     ; PgDn
  212.         mkeyw   '\khomscn',scan+0d0h    ; Home  Func PgUp
  213.         mkeyw   '\kendscn',scan+0d1h    ; End   Func PgDn
  214.         mkeyw   '\kupone',scan+0b0h     ; Ctrl PgUp     one line scrolls
  215.         mkeyw   '\kdnone',scan+0b1h     ; Ctrl PgDn
  216.         mkeyw   '\kmodeline',scan+0d2h  ; Kermit toggle mode line FuncIns
  217.         mkeyw   '\ktermtype',scan+0d3h  ; Kermit toggle terminal type FuncDel
  218.         mkeyw   '\kreset',scan+0d9h     ; Kermit reset terminal FuncBreak
  219.         mkeyw   '\kprtscn',scan+0bah    ; Kermit toggle print screen C-PrtSc
  220.         mkeyw   '\kdump',scan+0dah      ; Kermit Dump Screen FuncPrint
  221.         mkeyw   '\x7f',scan+38h         ; Del key sends DEL
  222.         mkeyw   '\x7f',scan+14          ; Backspace key sends DEL
  223. ;;;     mkeyw   '\kexit',scan+2093      ; Exit connect mode  Alt X
  224. ;;;     mkeyw   '\kstatus',scan+2079    ; Connect mode status  Alt S
  225.         mkeyw   '\kbreak',scan+60h      ; Send a Break  Break
  226.         mkeyw   '\khelp',scan+6fh       ; Connect mode drop down menu  Help
  227.         dw      0               ; end of table marker
  228.         ORG     offset loccount         ; restore current location counter
  229.  
  230. datas   ends
  231.  
  232. ;                       Documentation
  233. ;Translating a key:
  234. ;   The translator is called to obtain keyboard input; it sends characters to
  235. ; the serial port through standard controlled echo procedures or invokes
  236. ; named procedures. It returns carry clear when its operation is completed
  237. ; for normal actions and carry set when Connect mode must be exited. When
  238. ; Connect mode is exited the just read char should be passed in Kbdflg
  239. ; to msster.asm for invoking actions such as Status, send a break,
  240. ; quit connect mode; system dependent procedure Term is responsible for this.
  241. ;
  242. ;  Principal procedures are -
  243. ;       msuinit         Initializes keyboard translator in this file when
  244. ;                       Kermit first begins. Installs dfkey and shkey as the
  245. ;                       procedures used for Set Key and Show Key. Sys Indep.
  246. ;                       Called from msx or msy init procs. System Independent.
  247. ;       keybd           Performs the translation, outputs chars to the serial
  248. ;                       port or invokes a Kermit action routine. Sys Indep.
  249. ;       dfkey           Defines a key's translation. Reads command line
  250. ;                       via Kermit's command parser comnd. System Independent.
  251. ;       shkey           Shows translation of a key. Requests user to push
  252. ;                       selected key. System Independent.
  253. ;
  254. ;       kbdinit         optional. Initializes the translation tables when
  255. ;                       Kermit starts up. Called by msuinit. System Dependent.
  256. ;       getkey          Performs the keyboard read and returns results in
  257. ;                       a standardized system independent format. Sys Depend.
  258. ;       postkey         called by active translator after obtaining a keycode.
  259. ;                       Used to provide extra local actions (keyclick) only
  260. ;                       in Connect mode (not during Set/Show key commands).
  261. ;                       Called by keybd. System dependent.
  262. ; Supporting system independent procedures are -
  263. ; shkfre (show string free space), tstkeyw (finds user's keyword in the verb
  264. ; table), insertst (insert string in buffer), remstr (delete string in buffer).
  265. ;
  266. ;   System dependent procedure Getkey reads a keycode (usually via a Bios
  267. ; call). On IBM compatible machines this yields <ah=scan code, al=ascii>
  268. ; for ordinary keys, or <ah=scan code, al=0> for special keys such as F1,
  269. ; or <ah=0, al=###> when Alt### is used.
  270. ; For any system, the canonical output form is the key's code in Keycode.
  271. ; Place the ascii code (or scan code if none) in byte Keycode and ancillary
  272. ; info (shift states plus marker bit for scan codes) in byte Keycode + 1.
  273. ;
  274. ;   Table Aliaskey is a list of scan code/ascii codes for keys which appear
  275. ; more than once on a keyboard. This list is examined to distinguish such
  276. ; aliased keys (those on an auxillary keypad) from an ordinary ascii key,
  277. ; and the aliased key is then referenced by its scan code rather than by
  278. ; the ordinary ascii code. Aliaskey is machine and keyboard dependent.
  279. ;
  280. ;    Procedure Keybd calls Getkey for the Keycode, checks list of translatable
  281. ; keys Keylist, and then either sends an ascii string (one or more characters)
  282. ; or invokes a Kermit action verb. List Dirlist indicates what kind of
  283. ; translation to do. Keybd is system independent but may contain system
  284. ; dependent special actions such as echoing keyclicks. Keybd calls system
  285. ; dependent procedure Postkey just after calling getkey so local actions
  286. ; such as keyclicks can be activated only during Connect mode operations.
  287. ;
  288. ;    Keylist is a packed but unordered list of 16 bit keycodes which need
  289. ; translation. The lower order byte holds a key code (ascii char or scan code)
  290. ; while the high byte holds a scan code marker bit (0 if ascii code in low
  291. ; byte) plus any ancillary keyboard information such as Control/Shift/Alt/Meta
  292. ; keys being held down; these are of use in Show Key presentations.
  293. ;    Dirlist parallels Keylist to provide the kind of translation, verb or
  294. ; string, in the two highest bits with the other bits holding either
  295. ; a single new replacement character or the item number in lists of verbs
  296. ; or strings. If neither verb nor strng type bits are set in a dirlist
  297. ; word then the translation is a single new character held in the lower
  298. ; eight bits of that dirlist word.
  299. ;
  300. ;    The number of key translations is assembly constant Maxkeys (def 128).
  301. ;    The maximum number of strings is assembly constant Maxstngs (def 64).
  302. ;    The maximum number of verbs is 256 and is set by building table Kverbs.
  303. ;
  304. ;   For verbs, use the Item number from the Director table Dirlist to select
  305. ; a procedure offset from the structured list Kverbs and jump to that offset.
  306. ; Most verb procedures return carry clear to stay within Connect mode.
  307. ; Verbs requiring exiting Connect mode return carry set and may set byte
  308. ; Kbdflg to a char code which will be read by msster.asm for activating a
  309. ; transient Kermit action such as send a break (Kbdflg = 'b').
  310. ; Kbdflg is stored in msster.asm (as zero initially, meaning ignore it).
  311. ; Action verb procedures are normally located in a system dependent file.
  312. ;
  313. ;   For multi-char strings, use Item number from Director table Dirlist to
  314. ; select a pointer to a string. The list of string pointers is Sptable
  315. ; (string pointer table) which holds the offset in the data segment of the
  316. ; strings stored in buffer Stbuf. In stbuf strings are held as: one byte of
  317. ; length of following text and then the text itself (permits embedded nulls).
  318. ;  Use Chrout to send each string character, and finally return from Keybd
  319. ; with carry clear.
  320. ;
  321. ;   For single character replacements obtain the new character from the lower
  322. ; order byte of Director table Dirlist. If the character is Kermit's present
  323. ; escape character return from Keybd carry set to leave connect mode.
  324. ; Otherwise, send the character via Chrout and return from Keybd carry clear.
  325.  
  326. ; Keylist table format:
  327. ;    7 bits   1 bit   8 bits
  328. ; +----------+----+------------+ scan bit = 1 if key's code is non-ascii
  329. ; | aux info |scan| key's code | aux info = system dependent, used only to
  330. ; +----------+----+------------+            help identify key
  331. ;
  332. ; Dirlist table format            v s   meaning
  333. ;   1   1      14 bits            0 0   copy out one byte translation
  334. ; +---+---+--------------------+  1 0   copy out multi-char string number Item
  335. ; | v | s | item # or new char |  0 1   do action verb number Item
  336. ; +---+---+--------------------+  1 1   (not used)
  337. ;
  338. ; Table kverbs is organized by macro mkeyw as -
  339. ;       kverbs  db      number of table entries
  340. ;       (each entry is in the form below:)
  341. ;               db      number of bytes in verbname
  342. ;               db      'verbname'              variable length
  343. ;               db      '$'                     for printing
  344. ;               dw      value                   offset of procedure
  345. ;
  346. ;
  347. ;   Dfkey defines a key to be itself (undefines it) or a single replacement
  348. ; character or a character string or a Kermit action verb. Dfkey requires
  349. ; a command line so that it may be invoked by Take files but can be forced
  350. ; to prompt an interactive user to push a key. Syntax is discussed below.
  351. ; Note that redefined keys have their old definitions cleared so that
  352. ; old string space is reclaimed automatically.
  353. ;
  354. ;   Shkey displays a key's definition and the user is asked to push the
  355. ; selected key. The free space for strings is always shown afterward. See
  356. ; below for syntax.
  357. ;
  358. ;   Kbdinit is an optional routine called when Kermit starts up. It fills in
  359. ; the translation tables with desirable default values to save having to
  360. ; use long mskermit.ini files. The default values are stored in a structured
  361. ; table similar to (but not the same as) Dfkey's command lines; the keycode
  362. ; values are preset by hand to 16 bit numbers.
  363.  
  364. ;Defining a key:
  365. ; Command is SET KEY <key ident><whitespace><definition>
  366. ;
  367. ; <key ident> is
  368. ;               a single ordinary ascii char or
  369. ;               the numerical equivalent of an ascii char or
  370. ;               a Scan Code written as a number or
  371. ;               keyword SCAN followed by a number.
  372. ;               ?       Displays help message.
  373. ;       Numbers and Binary codes are of the form
  374. ;               \123    a decimal number
  375. ;               \o456   an octal number         base letters o, d, x can be
  376. ;               \d213   a decimal number        upper or lower case
  377. ;               \x0d    a hex number
  378. ;               \{b###}  braces around above material following slash.
  379. ;
  380. ; <whitespace> is one or more spaces and or tabs.
  381. ;
  382. ; <definition> is
  383. ;       missing altogether which "undefines" a key.
  384. ;       \Kverb          for a Kermit action verb; upper or lower case K is ok
  385. ;       \{Kverb}        ditto. Verb is the name of an action verb.
  386. ;       text            a string with allowed embedded whitespace and embedded
  387. ;                       binary chars as above. This kind of string may not
  388. ;                       commence with sequences \K or \{K; use braces below.
  389. ;       {text}          string confined to material within but excluding
  390. ;                       the braces. Note, where the number of opening braces
  391. ;                       exceeds the number of closing braces the end of line
  392. ;                       terminates the string: {ab{}{{c}d ==> ab{}{{c}d
  393. ;                       but  {ab}{{c}d ==> ab.
  394. ;       ?               Displays help message and lists all action verbs.
  395. ;
  396. ;       If Set Key is given interactively, as opposed to within a Take
  397. ;       file, the system will prompt for inputs if none is on the command
  398. ;       line. The response to Push key to be defined cannot be edited.
  399. ;
  400. ;       Text which reduces to a single replacement character is put into a
  401. ;       table separate from the multi-character strings (maxstng of these).
  402. ;       A key may be translated into any single 8 bit code.
  403. ;
  404. ;       Comments can follow a Kermit action verb or a braced string; no
  405. ;       semicolon is required since all are stripped out by the Take file
  406. ;       reader before the defining text is seen by SET KEY.
  407. ;
  408. ;       The current Kermit escape character cannot be translated without
  409. ;       subtrafuge.
  410. ;
  411. ;       Examples:
  412. ;               Set Key q z
  413. ;                               makes key q send character z
  414. ;               Set Key \7 \27[0m
  415. ;                               makes key Control G send the four byte
  416. ;                               string  ESC [ 0 m
  417. ;               Set Key q
  418. ;                               undefines key q so it sends itself (q) again.
  419. ;               Set Key \2349 \kexit
  420. ;                               defines IBM Alt-X to invoke the leave connect
  421. ;                               mode verb "exit" (Kermit's escape-char ^] C).
  422. ;               Set Key \x0c Login \{x0d}myname\{x0d}mypass\x0d
  423. ;                               defines Control L to send the string
  424. ;                               Login <cr>myname<cr>mypass<cr>
  425. ;
  426. ; Alternative Set Key syntax for backward compatibility with previous versions
  427. ;       The same forms as above except the key identification number must
  428. ;       be decimal and must Not have a leading backslash. Example:
  429. ;       Set Key Scan 59 This is the F1 key
  430. ;
  431. ;       If the definition is omitted it may be placed on the following line;
  432. ;       if that line is also empty the key is undefined (defined as Self).
  433. ;       A warning message about obsolete syntax will be given followed by
  434. ;       the key's modern numerical value and new definition. Only "special"
  435. ;       keys (those not producing ascii codes) are compatible with this
  436. ;       translator.
  437. ;
  438. ;Showing a key:
  439. ; Command is SHOW KEY <cr>
  440. ; System prompts user to press a key and shows the definition plus the
  441. ; free space for strings. Query response results in showing all definitions.
  442. ;                       End Documentation
  443.  
  444. code    segment public 'code'
  445.                 ; system independent external items
  446.         extrn   comnd:near, prompt:near                 ; in msscmd
  447.         extrn   strlen:near                             ; in mssfil
  448.         extrn   cnvlin:near, katoi:near, decout:near    ; in msster
  449.                 ; system dependent external items
  450.         extrn   beep:near, prtchr:near                  ; in msxibm &msyibm
  451.         extrn   anskbi:near                             ; in mszibm
  452.                 ; these are system dependent action verbs, in msxibm & msyibm
  453.         extrn   uparrw:near, dnarrw:near, rtarr:near, lfarr:near
  454.         extrn   pf1:near, pf2:near, pf3:near, pf4:near, kp0:near, kp1:near
  455.         extrn   kp2:near, kp3:near, kp4:near, kp5:near, kp6:near, kp7:near
  456.         extrn   kp8:near, kp9:near, kpminus:near, kpcoma:near, kpenter:near
  457.         extrn   kpdot:near
  458.         extrn   chrout:near, cstatus:near, cquit:near, cquery:near
  459.         extrn   vtans52:near, vtinit:near, dnwpg:near, upwpg:near
  460.         extrn   endwnd:near, homwnd:near, upone:near, dnone:near, trnprs:near
  461.         extrn   trnmod:near, sendbr:near, sendbl:near, dmpscn:near, snull:near
  462.         extrn   chang:near, klogon:near, klogof:near, cdos:near
  463.  
  464.         assume  cs:code, ds:datas, es:datas
  465.  
  466. ; Begin system independent Keyboard Translator code
  467.  
  468. ; MSUINIT performs Kermit startup initialization for this file.
  469. ; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
  470. ; are not initialized here then the older Set/Show Key procedures are called.
  471. MSUINIT PROC    NEAR                    ; call from msx/msy init code
  472.         call    kbdinit                 ; optional: init translator tables
  473.         mov     shkadr,offset shkey     ; declare keyboard translator present
  474.         mov     stkadr,offset dfkey     ; via Show and Set Key proc addresses
  475.         ret
  476. MSUINIT ENDP
  477.  
  478. ; Call Keybd to read a keyboard char (just returns carry clear if none) and
  479. ; 1) send the replacement string (or original char if not translated)
  480. ;    out the serial port, or
  481. ; 2) execute a Kermit action verb.
  482. ; Returns carry set if Connect mode is to be exited, else carry clear.
  483. ; Modifies registers ax and bx.
  484. KEYBD   PROC    NEAR                    ; active translator
  485.         call    getkey                  ; read keyboard
  486.         jnc     keybd1                  ; nc = data available
  487.         jmp     keybdx                  ; else just return carry clear
  488. keybd1: call    postkey                 ; call system dependent post processor
  489.         cmp     nkeys,0                 ; is number of keys defined = 0?
  490.         jz      keybd3                  ; z = none defined
  491.         push    di                      ; search keylist for this keycode
  492.         push    cx                      ; save some registers
  493.         push    es
  494.         mov     di,offset keylist       ; list of defined keycode words
  495.         mov     ax,keycode              ; present keycode
  496.         mov     cx,nkeys                ; number of words to examine
  497.         push    ds
  498.         pop     es                      ; make es:di point to datas segment
  499.         cld
  500.         repne   scasw                   ; find keycode in list
  501.         pop     es                      ; restore regs
  502.         pop     cx
  503.         je      keybd1b                 ; e = found, work with present di
  504.         pop     di                      ; restore original di
  505.         test    keycode,scan            ; is this a scan code?
  506.         jz      keybd3                  ; z = no, it's ascii, use al as char
  507.         call    beep                    ; say key is a dead one
  508.         clc
  509.         ret                             ; and exit with no action
  510.  
  511. keybd1b:sub     di,2                    ; correct for auto increment
  512.         sub     di,offset keylist       ; subtract start of list ==> listptr
  513.         mov     ax,dirlist[di]          ; ax = contents of director word
  514.         pop     di                      ; restore original di
  515.                                         ; dispatch on Director code
  516.         test    ax,verb                 ; verb only?
  517.         jnz     keyvb                   ; e = yes
  518.         test    ax,strng                ; multi-char string only?
  519.         jnz     keyst                   ; e = yes, else single char & no xlat.
  520.                                         ;
  521.                                         ; do single CHAR output (char in al)
  522. keybd3: cmp     al,trans.escchr         ; Kermit's escape char?
  523.         je      keybd3a                 ; e = yes, handle separately
  524.         call    chrout                  ; transmit the char
  525.         clc                             ; return success
  526.         ret
  527. keybd3a:stc                             ; set carry for jump to Quit
  528.         ret
  529.  
  530. keyvb:  and     ax,not(verb+strng)      ; VERB (ax=index, remove type bits)
  531.         mov     bx,offset kverbs        ; start of verb table
  532.         cmp     al,byte ptr [bx]        ; index > number of entries?
  533.         jae     keybdx                  ; ae = illegal, indices start at 0
  534.         inc     bx                      ; bx points to first entry
  535.         push    cx                      ; save reg
  536.         mov     cx,ax                   ; save the index in cx
  537.         inc     cx                      ; counter, indices start at 0
  538. keyvb1: mov     al,byte ptr [bx]        ; cnt value
  539.         xor     ah,ah
  540.         add     ax,4                    ; skip text and '?' and value word
  541.         add     bx,ax                   ; look at next slot
  542.         loop    keyvb1                  ; walk to correct slot
  543.         sub     bx,2                    ; backup to value field
  544. keyvb2: pop     cx                      ; restore reg
  545.         mov     bx,[bx]                 ; get value field of this slot
  546.         cmp     bx,0                    ; jump address defined?
  547.         je      keybdx                  ; e = no, skip the action
  548.         jmp     bx                      ; perform the function
  549.  
  550. keyst:  and     ax,not(verb+strng)      ; STRING (ax=index, remove type bits)
  551.         shl     ax,1                    ; convert to word index
  552.         push    si                      ; save working reg
  553.         mov     si,ax                   ; word subscript in table
  554.         mov     si,sptable[si]          ; memory offset of selected string
  555.         cmp     si,0                    ; is there a string pointer present?
  556.         je      keyst3                  ; e = no, skip operation
  557.         cld                             ; scan forward
  558.         lodsb                           ; get string length byte
  559.         mov     cl,al
  560.         xor     ch,ch                   ; to cx for looping
  561.         jcxz    keybdx                  ; z = null length
  562. keyst2: lodsb                           ; get new string char into al
  563.         push    si                      ; save si and cx around call
  564.         push    cx
  565.         call    chrout                  ; send out the char in al
  566.         pop     cx                      ; recover regs
  567.         pop     si
  568.         loop    keyst2                  ; loop through whole string
  569. keyst3: pop     si                      ; restore reg
  570.  
  571. keybdx: clc                             ; return success
  572.         ret
  573. KEYBD   ENDP
  574.  
  575. ; SET KEY - define a key   (procedure dfkey)
  576. ; SET KEY <key ident><whitespace><new meaning>
  577. ; Call from Kermit level. Returns as ret if failure or as rskp if success.
  578. ;
  579. DFKEY   PROC    NEAR                    ; define a key as a verb or a string
  580.         mov     keycode,0               ; clear keycode
  581.         mov     oldform,0               ; say no old form Set Key yet
  582.         mov     dx,offset tranbuf       ; our work space
  583.         mov     word ptr tranbuf,0      ; insert terminator
  584.         mov     bx,offset dfhelp1       ; first help message
  585.         mov     ah,cmfile               ; parse a word
  586.         call    comnd                   ; get key code or original ascii char
  587.          nop
  588.          nop
  589.          nop
  590.         mov     al,intake               ; reading from Take file indirectly
  591.         or      al,taklev               ; ditto, directly
  592.         mov     msutake,al              ; save here
  593.         or      ah,ah                   ; any text given?
  594.         jnz     dfkey12                 ; nz = yes, so don't consider prompts
  595.                                         ; interactive key request
  596.         cmp     intake,0                ; in a Take file?
  597.         je      dfkey10                 ; e = no, prompt for keystroke
  598.         jmp     dfkey0                  ;  else say bad syntax
  599. dfkey10:mov     ah,prstr
  600.         mov     dx,offset dfaskky       ; ask for key to be pressed
  601.         int     dos
  602. dfkey11:call    getkey                  ; read key ident from keyboard
  603.         jc      dfkey11                 ; c = no response, wait for keystroke
  604.         mov     ah,prstr                ; display cr/lf
  605.         mov     dx,offset crlf
  606.         int     dos
  607.         call    shkey0                  ; show current definition (in SHKEY)
  608.         jmp     dfkey1e                 ; prompt for and process definition
  609.  
  610. dfkey12:                                ; Look for word SCAN and ignore it
  611.         mov     dx,word ptr tranbuf     ; get first two characters
  612.         or      dx,2020h                ; map upper to lower case
  613.         cmp     dx,'cs'                 ; first two letters of word "scan"?
  614.         je      dfkey                   ; e = yes, skip the word
  615.         cmp     dx,'lc'                 ; first two letters of word "clear"?
  616.         je      dfkeyc                  ; e = yes, reinit keyboard
  617.         cmp     dx,'fo'                 ; first two letters of "off"
  618.         je      dfkey13                 ; e = yes, use DOS keyboard calls
  619.         cmp     dx,'no'                 ; first two letters of "on"
  620.         je      dfkey14                 ; e = yes, use standard kbd calls
  621.         cmp     ah,1                    ; number of characters received
  622.         ja      dfkey1                  ; a = more than one, decode
  623.         mov     ah,byte ptr tranbuf     ; get the single char
  624.         mov     byte ptr keycode,ah     ; store as ascii keycode
  625.         jmp     dfkey1b                 ; go get definition
  626.  
  627. dfkey13:mov     dosflg,0ffh             ; set DOS keyboard read flag
  628.         jmp     rskp
  629. dfkey14:mov     dosflg,0                ; clear DOS keyboard read flag
  630.         jmp     rskp
  631.  
  632. dfkey0: mov     dx,offset dfhelp1       ; say bad definition command
  633.         mov     ah,prstr
  634.         int     dos
  635.         jmp     rskp
  636.  
  637. dfkeyc:                                 ; CLEAR key defs, restore startup defs
  638.         mov     cx,maxkeys              ; size of keycode tables
  639.         push    es                      ; save register
  640.         push    ds
  641.         pop     es                      ; make es point to datas segment
  642.         mov     ax,0                    ; null, value to be stored
  643.         mov     di,offset dirlist       ; director table
  644.         cld
  645.         rep     stosw                   ; clear it
  646.         mov     cx,maxkeys
  647.         mov     di,offset keylist       ; keycode table
  648.         rep     stosw                   ; clear it
  649.         mov     cx,maxstng
  650.         mov     di,offset sptable       ; string pointer table
  651.         rep     stosw                   ; clear it
  652.         pop     es                      ; recover register
  653.         mov     strmax,offset stbuf     ; clear string buffer, free space ptr
  654.         mov     stbuf,0                 ; first element of buffer
  655.         mov     nkeys,0                 ; clear number of defined keys
  656.         call    msuinit                 ; restore startup definitions
  657.         jmp     rskp
  658.                                         ; Multi-char key identification
  659. dfkey1: mov     si,offset tranbuf       ; point to key ident text
  660.         cmp     byte ptr [si],'0'       ; is first character numeric?
  661.         jb      dfkey1a                 ; b = no
  662.         cmp     byte ptr [si],'9'       ; in numbers?
  663.         ja      dfkey1a                 ; a = no
  664.         mov     keycode,scan            ; setup keycode for scan value
  665.         mov     dx,si                   ; get length of string in cx
  666.         call    strlen
  667.         push    ds
  668.         pop     es                      ; make es point to datas segment
  669.         push    si
  670.         add     si,cx                   ; point at string terminator
  671.         mov     di,si
  672.         inc     di                      ; place to store string (1 byte later)
  673.         inc     cx                      ; include null terminator
  674.         std                             ; work backward
  675.         rep     movsb                   ; move string one place later
  676.         cld
  677.         pop     si
  678.         mov     byte ptr [si],'\'       ; make ascii digits into \nnn form
  679.         mov     oldform,0ffh            ; set old form flag
  680.         mov     dx,offset kwarnmsg      ; tell user this is old form
  681.         mov     ah,prstr
  682.         int     dos
  683. dfkey1a:call    katoi                   ; convert ascii number to binary in ax
  684.         jc      dfkey0                  ; c = no number converted
  685.         or      keycode,ax              ; store in keycode
  686.  
  687. dfkey1b:                                ; Get Definition proper
  688.         test    oldform,0ffh            ; old form Set Key active?
  689.         jz      dfkey1f                 ; z = no
  690.         mov     bx,offset tranbuf       ; get new definition on main cmd line
  691.         mov     word ptr [bx],0         ; insert terminator
  692.         mov     dx,offset dfhelp2       ; help for definition of key
  693.         mov     ah,cmtxt                ; read rest of line into tranbuf
  694.         call    comnd
  695.          nop                            ; allow null definitions
  696.          nop
  697.          nop
  698.         or      ah,ah                   ; char count zero?
  699.         jz      dfkey1e                 ; z = zero, prompt for definition
  700.         jmp     dfkey1g                 ; process definition
  701.  
  702. dfkey1e:mov     ah,prstr
  703.         mov     dx,offset crlf
  704.         int     dos
  705.         mov     dx,offset dfaskdf       ; prompt for definition string
  706.         call    prompt                  ; Kermit prompt routine
  707.         mov     comand.cmcr,1           ; permit bare carriage returns
  708. dfkey1f:mov     bx,offset tranbuf       ; get new definition
  709.         mov     word ptr [bx],0         ; insert terminator
  710.         mov     dx,offset dfhelp2       ; help for definition of key
  711.         mov     ah,cmtxt                ; read rest of line into tranbuf
  712.         call    comnd
  713.          jmp r                          ; exit now on ^C from user
  714.          nop
  715.         cmp     comand.cmcr,0           ; prompting for definition?
  716.         je      dfkey1g                 ; e = no, trim leading whitespace
  717.         mov     comand.cmcr,0           ; turn off allowance for bare c/r's
  718.         jmp     dfkey2                  ; interactive, allow leading whitespace
  719. dfkey1g:xchg    ah,al                   ; put byte count in al
  720.         xor     ah,ah                   ; clear high byte
  721.         mov     kbtemp,ax               ; and save count in kbtemp
  722.         mov     ah,cmcfm                ; get a confirm
  723.         call    comnd
  724.          jmp    r                       ; none so declare parse error
  725.          nop                            ; round out to three bytes
  726.         mov     cx,kbtemp               ; string length
  727.         jcxz    dfkey2                  ; z = empty string
  728.         push    si
  729.         push    di
  730.         mov     si,offset tranbuf       ; strip leading white space
  731. dfkey1c:cld                             ; work forward
  732.         lodsb                           ; read string char into al
  733.         dec     cx                      ; number of chars left to read
  734.         cmp     al,' '                  ; a space?
  735.         je      dfkey1c                 ; e = yes, keep going
  736.         cmp     al,tab                  ; tab?
  737.         je      dfkey1c                 ; e = yes, keep going
  738.         dec     si                      ; offset inc si in lodsb
  739.         add     cx,2                    ; include terminator, offset dec above
  740.         jcxz    dfkey1d                 ; z = nothing to move
  741.         mov     di,offset tranbuf       ; destination is start of buffer
  742.         push    ds
  743.         pop     es
  744.         cld
  745.         rep     movsb                   ; copy text part of string
  746. dfkey1d:pop     di
  747.         pop     si
  748.  
  749. dfkey2:                                 ; Examine translation
  750.         mov     al,trans.escchr         ; current escape char (port dependent)
  751.         cmp     al,byte ptr keycode     ; is this Kermit's escape char?
  752.         jne     dfkey2a                 ; ne = no
  753.         test    keycode,scan            ; see if scan code
  754.         jnz     dfkey2a                 ; nz = scan, so not ascii esc char
  755.         mov     dx,offset dfkopps       ; Opps! msg
  756.         mov     ah,prstr                ; complain and don't redefine
  757.         int     dos
  758.         jmp     rskp
  759.  
  760. dfkey2a:push    di                      ; get a director code for this key
  761.         push    cx
  762.         mov     di,offset keylist       ; list of keycodes
  763.         mov     cx,nkeys                ; number currently defined
  764.         mov     ax,keycode              ; present keycode
  765.         jcxz    dfkey2b                 ; cx = 0 means none defined yet
  766.         cld
  767.         push    ds
  768.         pop     es
  769.         repne   scasw                   ; is current keycode in the list?
  770.         jne     dfkey2b                 ; ne = not in list
  771.         sub     di,2                    ; correct for auto increment
  772.         sub     di,offset keylist
  773.         mov     listptr,di              ; list pointer for existing definition
  774.         pop     cx
  775.         pop     di
  776.         jmp     dfkey3                  ; go process definition
  777.  
  778. dfkey2b:pop     cx                      ; key not currently defined so
  779.         pop     di                      ;  make a new director entry for it
  780.         mov     bx,nkeys                ; number of keys previously defined
  781.         cmp     bx,maxkeys              ; enough space?
  782.         jae     dfkey2c                 ; ae = no, complain
  783.         shl     bx,1                    ; count words
  784.         mov     listptr,bx              ; index into word list
  785.         mov     ax,keycode              ; get key's code
  786.         mov     keylist[bx],ax          ; store it in list of keycodes
  787.         mov     dirlist[bx],0           ; clear the new director entry
  788.         inc     nkeys                   ; new number of keys
  789.         jmp     dfkey3                  ; go process definition
  790.  
  791. dfkey2c:mov     dx,offset keyfull       ; say key space is full already
  792.         mov     ah,prstr
  793.         int     dos
  794.         jmp     rskp                    ; tell parser we are happy
  795. ; listptr has element number in keylist or dirlist; keycode has key's code.
  796.  
  797. ; Parse new definition. First look for Kermit verbs as a line beginning
  798. ; as \K or \{K. Otherwise, consider the line to be a string.
  799. ; In any case, update the Director table for the new definition.
  800.  
  801. dfkey3: mov     brace,0                 ; assume not using braces
  802.         mov     si,offset tranbuf       ; start of definition text
  803.         cmp     byte ptr [si],'\'       ; starts with escape char?
  804.         jne     dfkey5                  ; ne = no, so we have a string
  805.         inc     si                      ; skip the backslash
  806.         cmp     byte ptr [si],braceop   ; starts with \{?
  807.         jne     dfkey3a                 ; ne = no
  808.         inc     si                      ; skip the opening brace
  809.         mov     brace,bracecl           ; expect closing brace
  810. dfkey3a:cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  811.         je      dfkey3b                 ; e = yes
  812.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  813.         jne     dfkey5                  ; ne = no, then it's a string
  814. dfkey3b:inc     si                      ; yes, skip the K too
  815.                                         ; Kermit action VERBS
  816.         push    si                      ; save verb name start address
  817. dfkey4: cld
  818.         lodsb                           ; scan til closing brace or w/s or end
  819.         cmp     al,0                    ; premature end?
  820.         je      dfkey4b                 ; e = yes, accept without brace
  821.         cmp     al,brace                ; closing brace?
  822.         je      dfkey4b                 ; e = yes
  823.         cmp     al,spc                  ; white space or control char?
  824.         ja      short dfkey4            ; a = no, so not at end yet
  825. dfkey4b:mov     byte ptr[si-1],0        ; insert null terminator
  826.         pop     si                      ; recover start address
  827.         call    tstkeyw                 ; find keyword, kw # returned in kbtemp
  828.         jc      dfkey4d                 ; c = no keyword found, complain
  829.         call    remstr                  ; clear old string, if string
  830.         mov     ax,kbtemp               ; save keyword number
  831.         and     ax,not(verb+strng)      ; clear verb / string field
  832.         or      ax,verb                 ; set verb ident
  833.         mov     si,listptr
  834.         mov     dirlist[si],ax          ; store info in Director table
  835.         jmp     dfkey7                  ; show results and return success
  836.  
  837. dfkey4d:mov     dx,offset verbbad       ; say no such verb
  838.         mov     ah,prstr
  839.         int     dos
  840.         jmp     rskp
  841.  
  842. ; Here we are left with the definition string; si points to its start, and
  843. ; kbtemp holds its length (number of bytes). Null termination. If the string
  844. ; begins with an opening brace it terminates on a matching closing brace
  845. ; or the end of line, whichever occurs first. Trailing whitespace removed
  846. ; before examining braces.
  847. ; Null length strings mean define key as Self.
  848.                                         ; STRING definitions
  849. dfkey5: call    remstr                  ; first, clear old string, if any
  850.         mov     si,offset tranbuf       ; si=source, di=dest, convert in-place
  851.         mov     di,si
  852.         call    cnvlin                  ; convert numbers, cx gets line length
  853.         mov     si,offset tranbuf       ; provide address of new string
  854.         cmp     cx,1                    ; just zero or one byte to do?
  855.         jbe     dfkey6                  ; e = yes, do as a char
  856.         call    insertst                ; insert new string, returns reg cx.
  857.         jc      dfkey5h                 ; c = could not do insert
  858.         mov     si,listptr              ; cx has type and string number
  859.         mov     dirlist[si],cx          ; update Director table from insertst
  860.         jmp     dfkey7                  ; show results and return success
  861.  
  862. dfkey5h:mov     dx,offset strbad        ; display complaint
  863.         mov     ah,prstr
  864.         int     dos
  865. dfkeyx: jmp     rskp
  866.  
  867.                 ; define SINGLE CHAR replacement or CLEAR a key definition.
  868.                 ; cx has char count 1 (normal) or 0 (to undefine the key).
  869. dfkey6: jcxz    dfkey6c                 ; z = cx= 0, clear definition
  870.         mov     al,byte ptr [si]        ; get first byte from definition
  871.         xor     ah,ah                   ; set the type bits to Char
  872.         mov     si,listptr
  873.         mov     dirlist[si],ax          ; store type and key's new code
  874.         jmp     dfkey7                  ; return success
  875.  
  876. dfkey6c:push    si                      ; clear a definition,
  877.         push    di                      ; listptr points to current def
  878.         mov     si,listptr              ; starting address to clear
  879.         add     si,offset dirlist
  880.         mov     di,si                   ; destination
  881.         add     si,2                    ; source is next word
  882.         mov     cx,nkeys                ; current number of keys defined
  883.         add     cx,cx                   ; double for listptr being words
  884.         sub     cx,listptr              ; cx = number of words to move
  885.         shr     cx,1                    ; convert to actual number of moves
  886.         jcxz    dfkey6d                 ; z = none, just remove last word
  887.         push    es
  888.         push    ds
  889.         pop     es                      ; make es:di point to datas segment
  890.         cld
  891.         push    cx                      ; save cx
  892.         rep     movsw                   ; move down higher list items
  893.         pop     cx
  894.         mov     si,listptr              ; do keylist too, same way
  895.         add     si,offset keylist
  896.         mov     di,si
  897.         add     si,2
  898.         rep     movsw
  899.         pop     es
  900. dfkey6d:mov     si,nkeys                ; clear old highest list element
  901.         shl     si,1                    ; address words
  902.         mov     dirlist[si],0           ; null the element
  903.         mov     keylist[si],0           ; null the element
  904.         dec     nkeys                   ; say one less key defined now
  905.         pop     di                      ; restore saved registers
  906.         pop     si
  907.  
  908. dfkey7: mov     ah,msutake              ; Finish up. In a Take file?
  909.         or      ah,taklev               ; or even directly
  910.         cmp     ah,0
  911.         je      dfkey7a                 ; e = no
  912.         cmp     flags.takflg,0          ; echo Take commands?
  913.         je      dfkey7b                 ; e = no
  914. dfkey7a:mov     ah,prstr                ; display cr/lf
  915.         mov     dx,offset crlf
  916.         int     dos
  917.         call    shkey0                  ; show new definition (in SHKEY)
  918.         call    shkfre                  ; show free string space
  919. dfkey7b:jmp     rskp                    ; return success
  920. DFKEY   ENDP
  921.  
  922. ; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
  923. ; command. Replaces obsolete procedure in msx---.
  924. ; Prompts for a key and shows that key's (or all if ? entered) keycode,
  925. ; definition, and the key definition free space remaining.
  926.  
  927. SHKEY   PROC    NEAR                    ; Show key's definition command
  928.         mov     ah,cmcfm                ; get a confirm
  929.         call    comnd
  930.          nop                            ; ignore any additional text
  931.          nop
  932.          nop
  933.         push    bx
  934.         mov     dx,offset shkmsg1       ; ask for original key
  935.         mov     ah,prstr
  936.         int     dos
  937. shky0:  call    getkey                  ; read keyboard, output to keycode
  938.         jc      shky0                   ; wait for a key (c = nothing there)
  939.         cmp     byte ptr keycode,'?'    ; query for all keys?
  940.         jne     shky0a                  ; ne = no, not a query
  941.         test    keycode,scan            ; is this a scan code, vs ascii query?
  942.         jz      shky0c                  ; z = no Scan, so it is a query
  943.  
  944. shky0a: mov     ah,prstr                ; show single key. Setup display
  945.         mov     dx,offset crlf
  946.         int     dos
  947.         call    shkey0                  ; show just one key
  948. shky0b: call    shkfre                  ; show free string space
  949.         jmp     shkeyx                  ; exit
  950.  
  951. shky0c: mov     cx,nkeys                ; Show all keys. nkeys = number defined
  952.         jcxz    shky0b                  ; z = none to show
  953.         mov     si,offset keylist       ; list of definitions
  954.         push    si                      ; save pointer
  955. shky1:  pop     si                      ; recover pointer
  956.         cld
  957.         lodsw                           ; get a keycode
  958.         push    si                      ; save pointer
  959.         push    cx                      ; save counter
  960.         mov     keycode,ax              ; save new keycode
  961.         mov     ah,prstr
  962.         mov     dx,offset crlf
  963.         int     dos
  964.         call    shkey0                  ; show this keycode
  965.  
  966.         pop     cx                      ; pause between screens, recover cntr
  967.         push    cx                      ; save it again
  968.         dec     cx                      ; number yet to be shown
  969.         jcxz    shky1b                  ; z = have now shown all of them
  970.         mov     ax,nkeys                ; number of defined keys
  971.         sub     ax,cx                   ; minus number yet to be displayed
  972.         xor     dx,dx                   ; clear extended numerator
  973.         div     twelve                  ; two lines per definition display
  974.         or      dx,dx                   ; remainder zero (12 defs shown)?
  975.         jnz     shky1b                  ; nz = no, not yet so keep going
  976.         mov     ah,prstr
  977.         mov     dx,offset shkmsg3       ; "push any key to continue" msg
  978.         int     dos
  979. shky1a: call    getkey                  ; get any key
  980.         jc      shky1a                  ; c = nothing at keyboard yet, wait
  981. shky1b: pop     cx                      ; resume loop
  982.         loop    shky1
  983.         pop     si                      ; clean stack
  984.         call    shkfre                  ; show free string space
  985.         jmp     shkeyx                  ; exit
  986.  
  987.                 ; show key worker routine, called from above
  988.                                         ; SHKEY0 called by DFKEY just above
  989. SHKEY0: test    keycode,scan            ; scan code?
  990.         jz      shkey1                  ; z = no, regular ascii
  991.  
  992.                                         ; SCAN codes
  993.         mov     dx,offset scanmsg       ; say Scan Code:
  994.         mov     ah,prstr
  995.         int     dos
  996.         mov     ah,conout
  997.         mov     dl,'\'                  ; add backslash before number
  998.         int     dos
  999.         mov     ax,keycode              ; get key's code again
  1000.         call    decout                  ; display 16 bit decimal keycode
  1001.         jmp     shkey2                  ; go get definition
  1002.  
  1003. shkey1: mov     dx,offset ascmsg        ; say ASCII CHAR
  1004.         mov     ah,prstr
  1005.         int     dos
  1006.         mov     dl,byte ptr keycode     ; get ascii code (al part of input)
  1007.         mov     ah,conout
  1008.         cmp     dl,spc                  ; control code?
  1009.         jae     shkey1a                 ; ae = no
  1010.         push    dx                      ; save char
  1011.         mov     dl,5eh                  ; show caret first
  1012.         int     dos
  1013.         pop     dx
  1014.         add     dl,'A'-1                ; ascii bias
  1015. shkey1a:cmp     dl,del                  ; DEL?
  1016.         jne     shkey1b                 ; ne = no
  1017.         mov     dl,'D'                  ; spell out DEL
  1018.         int     dos
  1019.         mov     dl,'E'
  1020.         int     dos
  1021.         mov     dl,'L'
  1022. shkey1b:int     dos
  1023.         mov     dl,spc                  ; add a couple of spaces
  1024.         int     dos
  1025.         int     dos
  1026.         mov     dl,'\'                  ; add backslash before number
  1027.         int     dos
  1028.         mov     ax,keycode              ; show 16 bit keycode in decimal
  1029.         call    decout                  ; and go get definiton
  1030.  
  1031.                                         ; Display defintion
  1032. shkey2: mov     dx,offset shkmsg2       ; intermediate part of reply
  1033.         mov     ah,prstr                ; " is defined as "
  1034.         int     dos
  1035.         push    di                      ; get a director code for this key
  1036.         push    cx
  1037.         mov     di,offset keylist       ; list of keycodes
  1038.         mov     cx,nkeys                ; number currently defined
  1039.         jcxz    shkey2a                 ; z = none
  1040.         mov     ax,keycode              ; present keycode
  1041.         push    ds
  1042.         pop     es                      ; use datas segment for es:di
  1043.         cld
  1044.         repne   scasw                   ; is current keycode in the list?
  1045.         jne     shkey2a                 ; ne = not in list
  1046.         sub     di,2                    ; correct for auto increment
  1047.         sub     di,offset keylist
  1048.         mov     listptr,di              ; list pointer for existing definition
  1049.         pop     cx
  1050.         pop     di
  1051.         jmp     shkey3                  ; go process definition
  1052.  
  1053. shkey2a:pop     cx
  1054.         pop     di
  1055.         mov     dx,offset noxmsg        ; say Self (no translation)
  1056.         mov     ah,prstr
  1057.         int     dos
  1058.         ret                             ; return to main show key loop
  1059.  
  1060. shkey3:                                 ; translations, get kind of.
  1061.         mov     si,listptr
  1062.         test    dirlist[si],verb        ; defined as verb?
  1063.         jnz     shkey6                  ; nz = yes, go do that one
  1064.         test    dirlist[si],strng       ; defined as string?
  1065.         jz      shkey3a                 ; z = no
  1066.         jmp     shkey8                  ; yes, do string display
  1067. shkey3a:
  1068.         mov     dx,offset ascmsg        ; CHAR. say 'Ascii char:'
  1069.         mov     ah,prstr
  1070.         int     dos
  1071.         mov     ax,dirlist [si]         ; get type and char
  1072.         mov     dl,al                   ; put char here for display
  1073.         push    ax                      ; save here too
  1074.         mov     ah,conout
  1075.         cmp     dl,spc                  ; control code?
  1076.         jae     shkey4                  ; ae = no
  1077.         push    dx
  1078.         mov     dl,5eh                  ; show caret
  1079.         int     dos
  1080.         pop     dx
  1081.         add     dl,'A'-1                ; add ascii bias
  1082. shkey4: cmp     dl,del                  ; DEL?
  1083.         jne     shkey4a                 ; ne = no
  1084.         mov     dl,'D'                  ; spell out DEL
  1085.         int     dos
  1086.         mov     dl,'E'
  1087.         int     dos
  1088.         mov     dl,'L'
  1089. shkey4a:int     dos
  1090.         mov     dl,spc                  ; add a couple of mov     dl,spaces
  1091.         mov     ah,conout
  1092.         int     dos
  1093.         int     dos
  1094.         mov     dl,'\'                  ; add backslash before number
  1095.         int     dos
  1096.         pop     ax                      ; recover char
  1097.         xor     ah,ah                   ; clear high byte
  1098.         call    decout                  ; show decimal value
  1099.         ret                             ; return to main show key loop
  1100.  
  1101. shkey6: mov     ah,prstr                ; VERB
  1102.         mov     dx,offset verbmsg       ; say 'verb'
  1103.         int     dos
  1104.         mov     si,listptr              ; get verb index from director
  1105.         mov     dx,dirlist[si]
  1106.         and     dx,not(verb+strng)      ; remove type bits, leaves verb number
  1107.         mov     bx,offset kverbs        ; table of verbs & actions
  1108.         mov     al,byte ptr [bx]        ; number of keywords
  1109.         xor     ah,ah
  1110.         dec     ax
  1111.         mov     kwcnt,ax                ; save number of last one here
  1112.         cmp     dx,ax                   ; asking for more than we have?
  1113.         ja      shkeyx                  ; a = yes, exit bad
  1114.         inc     bx                      ; point to first slot
  1115.         mov     cx,0                    ; current slot number
  1116. shkey6b:cmp     cx,dx                   ; this slot?
  1117.         je      shkey6c                 ; e = yes, print the text part
  1118.         ja      shkeyx                  ; a = beyond, exit bad
  1119.         mov     al,byte ptr [bx]        ; get cnt (keyword length)
  1120.         xor     ah,ah
  1121.         add     ax,4                    ; skip over '$' and two byte value
  1122.         add     bx,ax                   ; bx = start of next keyword slot
  1123.         inc     cx                      ; current keyword number
  1124.         jmp     short shkey6b           ; try another
  1125. shkey6c:inc     bx                      ; look at text field
  1126.         mov     dx,bx                   ; offset for printing
  1127.         mov     ah,prstr
  1128.         int     dos
  1129.         mov     ah,conout
  1130.         mov     dl,spc                  ; add a couple of spaces
  1131.         int     dos
  1132.         int     dos
  1133.         mov     dl,'\'                  ; show verb name as \Kverb
  1134.         int     dos
  1135.         mov     dl,'K'
  1136.         int     dos
  1137.         mov     ah,prstr
  1138.         mov     dx,bx                   ; show name part again
  1139.         int     dos
  1140.         ret                             ; return to main show key loop
  1141.  
  1142. shkey8: mov     ah,prstr                ; STRING
  1143.         mov     dx,offset strngmsg      ; say String:
  1144.         int     dos
  1145.         mov     si,listptr              ; get index from director
  1146.         mov     bx,dirlist[si]
  1147.         and     bx,not(verb+strng)      ; remove type bits
  1148.         shl     bx,1                    ; index words
  1149.         mov     si,sptable[bx]          ; table of string offsets
  1150.         mov     cl,byte ptr [si]        ; get string length byte
  1151.         xor     ch,ch
  1152.         inc     si                      ; point to string text
  1153.         mov     ah,conout
  1154. shkey8a:cld
  1155.         lodsb                           ; get a byte
  1156.         cmp     al,spc                  ; control code?
  1157.         jae     shkey8b                 ; ae = no
  1158.         push    ax
  1159.         mov     dl,5eh                  ; show caret first
  1160.         int     dos
  1161.         pop     ax
  1162.         add     al,40h                  ; convert to printable for display
  1163. shkey8b:mov     dl,al
  1164.         int     dos                     ; display it
  1165.         loop    shkey8a                 ; do another
  1166.         ret                             ; return to main show key loop
  1167.  
  1168. shkeyx: pop     bx                      ; restore reg
  1169.         jmp     rskp                    ; return success
  1170. SHKEY   ENDP
  1171.  
  1172. ;;;     keyboard translator local support procedures, system independent
  1173.  
  1174. ; Tstkeyw checks text word pointed to by si against table of keywords (pointed
  1175. ; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
  1176. ; Returns in kbtemp the number of the keyword and carry clear, or if failure
  1177. ; returns kbtemp zero and carry set.
  1178. ; Keyword structure is:         db      cnt     (length of string 'word')
  1179. ;                               db      'word'  (keyword string)
  1180. ;                               db      '$'     (printing terminator)
  1181. ;                               dw      value   (value returned in bx)
  1182. ; Make these with macro mkeyw such as   mkeyw 'test',15   with the list of
  1183. ; such keywords headed by a byte giving the number of keywords in the list.
  1184. tstkeyw proc    near
  1185.         push    ax
  1186.         push    cx
  1187.         push    si
  1188.         mov     verblen,0               ; verblen will hold verb length
  1189.         push    si                      ; save user's verb pointer
  1190. tstkw1: cld
  1191.         lodsb                           ; get a verb character
  1192.         cmp     al,spc                  ; verbs are all non-spaces and above
  1193.         jbe     tstkw2                  ; be = done (space or control char)
  1194.         inc     verblen                 ; count verb length
  1195.         jmp     short tstkw1            ; printable char, look for more
  1196. tstkw2: pop     si                      ; pointer to verb
  1197.         mov     bx,offset kverbs        ; table of Kermit verb keywords
  1198.         mov     al,byte ptr [bx]        ; number of keywords
  1199.         xor     ah,ah
  1200.         mov     kwcnt,ax                ; save number of keywords here
  1201.         inc     bx                      ; point bx to first slot
  1202.         mov     kbtemp,0                ; remember which keyword
  1203.  
  1204. tstkw3:                                 ; match table keyword and text word
  1205.         mov     cx,verblen              ; length of user's verb
  1206.         cmp     byte ptr [bx],cl        ; compare length vs table keyword
  1207.         jne     tstkw4                  ; ne = not equal lengths, try another
  1208.         push    si                      ; lengths match, how about spelling?
  1209.         push    bx
  1210.         inc     bx                      ; point at start of keyword
  1211. tstkw3a:mov     ah,byte ptr [bx]        ; keyword char
  1212.         mov     al,byte ptr [si]        ; text char
  1213.         cmp     ah,'A'
  1214.         jb      tstkw3b                 ; b = control chars
  1215.         cmp     ah,'Z'
  1216.         ja      tstkw3b                 ; a = not upper case alpha
  1217.         add     ah,'a'-'A'              ; convert upper case to lower case
  1218. tstkw3b:cmp     al,'A'
  1219.         jb      tstkw3c
  1220.         cmp     al,'Z'
  1221.         ja      tstkw3c
  1222.         add     al,'a'-'A'              ; convert upper case to lower case
  1223. tstkw3c:cmp     al,ah                   ; test characters
  1224.         jne     tstkw3d                 ; ne = no match
  1225.         inc     si                      ; move to next char
  1226.         inc     bx
  1227.         loop    tstkw3a                 ; loop through entire length
  1228. tstkw3d:pop     bx
  1229.         pop     si
  1230.         jcxz    tstkw5                  ; z: cx = 0, exit with match;
  1231.                                         ;  else select next keyword
  1232. tstkw4: inc     kbtemp                  ; number of keyword to test next
  1233.         mov     cx,kbtemp
  1234.         cmp     cx,kwcnt                ; all done? Recall kbtemp starts at 0
  1235.         jae     tstkwx                  ;ae = exhausted search, unsuccessfully
  1236.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  1237.         xor     ah,ah
  1238.         add     ax,4                    ; skip over '$' and two byte value
  1239.         add     bx,ax                   ; bx = start of next keyword slot
  1240.         jmp     tstkw3                  ; do another comparison
  1241.  
  1242. tstkw5:                                 ; get action pointer
  1243.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  1244.         xor     ah,ah
  1245.         add     ax,2                    ; skip over '$'
  1246.         add     bx,ax                   ; now bx points to dispatch value
  1247.         mov     bx,[bx]                 ; bx holds dispatch value
  1248.         clc                             ; carry clear for success
  1249.         jmp     short tstkwxx           ; exit
  1250.         ret
  1251. tstkwx: xor     bx,bx                   ; exit when no match
  1252.         mov     kbtemp,bx               ; make verb number be zero too
  1253.         stc                             ; carry set for failure
  1254. tstkwxx:pop     si
  1255.         pop     cx
  1256.         pop     ax
  1257.         ret
  1258. tstkeyw endp
  1259.  
  1260. ; Insert asciiz string pointed to by si into string buffer stbuf.
  1261. ; Reg cx has string length upon entry.
  1262. ; Success: returns offset of first free byte (strmax) in string buffer stbuf,
  1263. ; cx = type and Index of new string, and carry clear.
  1264. ; Failure = carry set.
  1265. insertst proc   near
  1266.         push    bx
  1267.         push    dx
  1268.         push    si
  1269.         push    di
  1270.         push    kbtemp          ; save this variable too
  1271.         mov     dx,cx           ; save length of incoming string in dx
  1272.         mov     bx,offset sptable ; table of string offsets
  1273.         mov     kbtemp,0        ; slot number
  1274.         mov     cx,maxstng      ; number of entries, find an empty slot
  1275. insert1:cmp     word ptr[bx],0  ; slot empty?
  1276.         je      insert2         ; e = yes
  1277.         inc     kbtemp          ; remember slot number
  1278.         add     bx,2            ; look at next slot
  1279.         loop    insert1         ; keep looking
  1280.         jmp     short insert4   ; get here if no empty slots
  1281. insert2:                        ; see if stbuf has sufficient space
  1282.         mov     cx,dx           ; length of new string to cx
  1283.         mov     di,strmax       ; offset of first free byte in stbuf
  1284.         add     di,cx           ; di = address where this string would end
  1285.         cmp     di,offset stbuf+stbuflen ; beyond end of buffer?
  1286.         jae     insert4         ; ae = yes, not enough room
  1287.         mov     di,strmax       ; point to first free slot in stbuf
  1288.         mov     [bx],di         ; fill slot with address offset of buffer
  1289.         push    es
  1290.         push    ds
  1291.         pop     es              ; point es:di to datas segment
  1292.         cld
  1293.         mov     byte ptr [di],cl ; length of text for new string
  1294.         inc     di              ; move to next storage slot
  1295.         rep     movsb           ; copy string text
  1296.         pop     es
  1297.         mov     strmax,di       ; offset of next free byte
  1298.         mov     cx,kbtemp       ; return new slot number with Director Index
  1299.         and     cx,not(strng+verb) ; clear type bits
  1300.         or      cx,strng        ; say type is multi-char string
  1301.         clc                     ; say success
  1302.         jmp     short insertx   ; exit
  1303. insert4:stc                     ; say no-can-do
  1304. insertx:pop     kbtemp
  1305.         pop     di
  1306.         pop     si
  1307.         pop     dx
  1308.         pop     bx
  1309.         ret
  1310. insertst endp
  1311.  
  1312. ; Remove (delete) string. Enter with listptr preset for director entry.
  1313. ; Acts only on existing multi-char strings; recovers freed space.
  1314. ; All registers preserved.
  1315. remstr  proc    near
  1316.         push    si
  1317.         mov     si,listptr              ; list pointer
  1318.         test    dirlist[si],strng       ; multi-char string?
  1319.         pop     si
  1320.         jnz     remst1                  ; nz = a multi-char string
  1321.         ret                             ; else do nothing
  1322. remst1: push    ax
  1323.         push    bx
  1324.         push    cx
  1325.         push    dx
  1326.         push    si
  1327.         mov     si,listptr
  1328.         mov     ax,dirlist[si]          ; Director table entry
  1329.         and     ax,not(strng+verb) ; clear type bits, leave string's pointer
  1330.         mov     dirlist[si],0           ; clear Director table entry
  1331.         shl     ax,1                    ; index words not bytes
  1332.         mov     si,offset sptable       ; list of string offsets in stbuf
  1333.         add     si,ax                   ; plus index = current slot
  1334.         mov     bx,[si]                 ; get offset of string to be deleted
  1335.         mov     dx,bx                   ; save in dx for later
  1336.         mov     cl,byte ptr [bx]        ; get length byte
  1337.         xor     ch,ch                   ; get length of subject string
  1338.         inc     cx                      ; length byte too, cx has whole length
  1339.         sub     strmax,cx       ; count space to be freed (adj end-of-buf ptr)
  1340.         mov     word ptr [si],0 ; clear sptable of subject string address
  1341.         push    cx                      ; save length of purged string
  1342.         push    di                      ; save di
  1343.         push    si
  1344.         push    es                      ; save es
  1345.         push    ds
  1346.         pop     es              ; setup es:di to be ds:offset of string
  1347.         mov     di,dx           ; destination = start address of purged string
  1348.         mov     si,dx           ; source = start address of purged string
  1349.         add     si,cx           ;  plus string length of purged string.
  1350.         mov     cx,offset stbuf+stbuflen ; 1 + address of buffer end
  1351.         sub     cx,si                   ; 1 + number of bytes to move
  1352.         dec     cx                      ; number of bytes to move
  1353.         jcxz    remst2                  ; z = none
  1354.         cld                             ; direction is forward
  1355.         rep     movsb                   ; move down preserved strings
  1356. remst2: pop     es                      ; restore regs
  1357.         pop     di
  1358.         pop     si
  1359.         pop     ax              ; recover length of purged string (was in cx)
  1360.         mov     bx,offset sptable       ; string pointer table
  1361.         mov     cx,maxstng              ; max mumber of entries
  1362. remst4: cmp     [bx],dx         ; does this entry occur before purged string?
  1363.         jbe     remst5          ; be = before or equal, so leave it alone
  1364.         sub     [bx],ax         ; recompute address (remove old string space)
  1365. remst5: add     bx,2                    ; look at next list entry
  1366.         loop    remst4                  ; do all entries in sptable
  1367.         pop     si
  1368.         pop     dx
  1369.         pop     cx
  1370.         pop     bx
  1371.         pop     ax
  1372.         ret
  1373. remstr  endp
  1374.  
  1375. shkfre  proc    near                    ; show free key & string defs & space
  1376.         push    ax                      ; preserves all registers.
  1377.         push    bx
  1378.         push    cx
  1379.         push    dx
  1380.         push    kbtemp
  1381.         mov     dx,offset fremsg
  1382.         mov     ah,prstr
  1383.         int     dos
  1384.         mov     ax,maxkeys              ; max number of key defs
  1385.         sub     ax,nkeys                ; number currently used
  1386.         call    decout                  ; show the value
  1387.         mov     ah,prstr
  1388.         mov     dx,offset kyfrdef       ; give key defs msg
  1389.         int     dos
  1390.         mov     bx,offset sptable       ; table of string pointers
  1391.         mov     cx,maxstng              ; number of pointers
  1392.         mov     kbtemp,0                ; number free
  1393. shkfr1: cmp     word ptr [bx],0         ; slot empty?
  1394.         jne     shkfr2                  ; ne = no
  1395.         inc     kbtemp                  ; count free defs
  1396. shkfr2: add     bx,2                    ; look at next slot
  1397.         loop    shkfr1                  ; do all of them
  1398.         mov     ax,kbtemp               ; number of free defs
  1399.         call    decout                  ; display
  1400.         mov     dx,offset stfrdef       ; say free string defs
  1401.         mov     ah,prstr
  1402.         int     dos
  1403.         mov     ax,offset stbuf+stbuflen ; 1 + last byte in stbuf
  1404.         sub     ax,strmax               ; offset of last free byte in stbuf
  1405.         call    decout
  1406.         mov     dx,offset stfrspc       ; give free space part of msg
  1407.         mov     ah,prstr
  1408.         int     dos
  1409.         pop     kbtemp
  1410.         pop     dx
  1411.         pop     cx
  1412.         pop     bx
  1413.         pop     ax
  1414.         ret
  1415. shkfre  endp
  1416. ; Initialize the keyboard tables at Kermit startup time. Optional procedure.
  1417. ; Requires kbdinlst to be configured with mkeyw macro in the form
  1418. ;       mkeyw   'definition',keytype*256+keycode
  1419. ; keytype is 0 for scan codes and non-zero for ascii.
  1420. ; Returns normally.
  1421. kbdinit proc    near                    ; read keyword kbdinlst and setup
  1422.         push    ds                      ;  initial keyboard assignments.
  1423.         pop     es                      ; set es:di to datas segment
  1424.         inc     taklev                  ; pretend that we are in Take file
  1425.         mov     si,offset kbdinlst      ; start of list of definitions
  1426. kbdini1:mov     cl,byte ptr [si]        ; cnt field (keyword length of macro)
  1427.         xor     ch,ch
  1428.         jcxz    kbdinix                 ; z = null cnt field = end of list
  1429.         inc     si                      ; look at text field
  1430.         mov     di,offset tranbuf       ; where defkey expects text
  1431.         cld
  1432.         rep     movsb                   ; copy cx chars to tranbuf
  1433.         mov     byte ptr [di],0         ; insert null terminator
  1434.         inc     si                      ; skip '$' field
  1435.         mov     ax,word ptr [si]        ; get value field
  1436.         mov     keycode,ax              ; set key ident value
  1437.         push    si
  1438.         call    dfkey2                  ; put dfkey to work
  1439.          nop
  1440.          nop
  1441.          nop
  1442.         pop     si
  1443.         add     si,2                    ; point to next entry
  1444.         jmp     kbdini1                 ; keep working
  1445. kbdinix:dec     taklev                  ; reset Take file level
  1446.         ret
  1447. kbdinit endp
  1448. ;;;     End of System Independent Procedures
  1449.  
  1450. ;;;     Begin System Dependent Procedures
  1451.  
  1452. ; Read keyboard. System dependent.
  1453. ; Return carry set if nothing at keyboard.
  1454. ; If char present return carry clear with key's code in Keycode.
  1455. ; If key is ascii put that in the low byte of Keycode and clear bit Scan in
  1456. ; the high byte; otherwise, put the scan code in the lower byte and set bit
  1457. ; Scan in the high byte.
  1458. ; Bit Scan is set if key is not an ascii code.
  1459. ; Modifies register ax.
  1460. getkey  proc    near
  1461.         mov     ah,1                    ; anything at keyboard?
  1462.         int     kbint                   ; Bios keyboard interrupt
  1463.         jnz     getky1                  ; nz = char available
  1464.         stc                             ; carry set = nothing available
  1465.         jmp     short getkyx            ; exit on no char available
  1466. getky1: mov     keycode,0
  1467.         mov     ah,0                    ; read, no echo, wait til done
  1468.         int     kbint                   ; ==> ah = scan code, al = char value
  1469.         push    cx
  1470.         mov     cx,aliaslen             ; number of aliased keys
  1471.         or      cx,cx
  1472.         pop     cx
  1473.         jz      getky2                  ; z = none
  1474.         push    di                      ; check key (ax) for aliases
  1475.         push    cx
  1476.         push    es
  1477.         push    ds
  1478.         pop     es                      ; make es:di refer to datas segment
  1479.         mov     di,offset aliaskey      ; list of aliased keys
  1480.         mov     cx,aliaslen             ; number of entries
  1481.         cld
  1482.         repne   scasw                   ; look for a match
  1483.         pop     es
  1484.         pop     cx
  1485.         pop     di
  1486.         jne     getky2                  ; ne = not there
  1487.         mov     al,0                    ; force use of scan code (in ah)
  1488. getky2: or      al,al                   ; scan code being returned?
  1489.         jnz     getky3                  ; nz = no
  1490.         xchg    ah,al                   ; put scan code in al
  1491.         or      keycode,scan            ; set scan flag (vs ascii)
  1492. getky3: mov     byte ptr keycode,al     ; return key's code (usually ascii)
  1493.         clc                             ; carry clear = got a char
  1494. getkyx: ret
  1495. getkey  endp
  1496.  
  1497. ; Do any local processing after reading a key during active translation
  1498. ; Avoids same actions if a key is being defined or shown.
  1499. postkey proc    near
  1500.         ret
  1501. postkey endp
  1502.  
  1503. ; Jumping to this location is like retskp.  It assumes the instruction
  1504. ;   after the call is a jmp addr.
  1505.  
  1506. RSKP    PROC    NEAR
  1507.         pop bp
  1508.         add bp,3
  1509.         push bp
  1510.         ret
  1511. RSKP    ENDP
  1512.  
  1513. ; Jumping here is the same as a ret.
  1514.  
  1515. R       PROC    NEAR
  1516.         ret
  1517. R       ENDP
  1518.  
  1519. code    ends
  1520.         end
  1521.