home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s2.zip / MSUIBM.ASM < prev    next >
Assembly Source File  |  1988-02-12  |  87KB  |  1,703 lines

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