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

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