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

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