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

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