home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msup98.asm < prev    next >
Assembly Source File  |  2020-01-01  |  87KB  |  2,193 lines

  1.         NAME    msup98
  2. ; File MSUP98.ASM
  3. ; Keyboard translator for NEC PC-9801 by Hirofumi Fujii (KEK)
  4. ;
  5. ; 17-Apr-1991 Many modifications have been done by Joe Doupnik.
  6. ; 13-Aug-1990 the input for external procedure PROMPT has been changed
  7. ;             It accepts ASCIIZ string.  The 'dsafkdf' string has been
  8. ;             chagned to ASCIIZ for this purpose.
  9. ;
  10. ; 10-Dec-1988
  11. ; To use CTRL+SPACE, ROLL-UP, ROLL-DOWN etc., I introduced new scan codes.
  12. ; These scan codes are private, NOT the NEC codes. Therefore you must be
  13. ; careful for new models.
  14. ;
  15. ;                      Normal +SHIFT   +CTRL
  16. ;         SPACE         34h     A4h     B4h
  17. ;         ROLL-UP       36h     A6h     B6h
  18. ;         ROLL-DOWN     37h     A7h     B7h
  19. ;         INS           38h     A8h     B8h
  20. ;         DEL           39h     A9h     B9h
  21. ;         up arrow      3Ah     AAh     BAh
  22. ;         left arrow    3Bh     ABh     BBh
  23. ;         right arrow   3Ch     ACh     BCh
  24. ;         down arrow    3Dh     ADh     BDh
  25. ;         HOME CLR      3Eh     AEh     ---
  26. ;         HELP          3Fh     AFh     BFh
  27. ;
  28. ; Getkey has three modes, BIOS mode, CON mode and DOS mode. In the BIOS mode,
  29. ; keys are read by using NEC keyboard bios (int 18h).  The scan code of
  30. ; the key can be read as well as JIS-Roman code.  This method is quite safe
  31. ; for terminal emulation unless Japanese front end processor is used.
  32. ; In the CON mode, keys are read by using MS-DOS function call (int 21h).
  33. ; In this mode, the scan code of the key cannot be read.  Function keys,
  34. ; ROLL-UP, ROLL-DOWN, INS, DEL, arrow keys, HOME-CLR and HELP keys are
  35. ; programable, so that they can be programmed to return its scan code.
  36. ; However, numeric keys, minus, star, plus, equal, comma, period keys
  37. ; in the keypad are not programmed.  They cannot be distinguished from
  38. ; the nomal keys.  Therefore, a dangerous method is employed in this
  39. ; program to read the keypad keys.  If you feel something wrong at keypad
  40. ; keys, ESC, TAB or BS key, try to use in BIOS mode.
  41. ;
  42. ; Last edit 23 Oct 1988
  43. ; 23 Oct 1988  Special treatment for CTRL-@ (NUL).
  44. ; 30 Aug 1988  Keypad keys can be read in CON mode.
  45. ; 16 Jul 1988  all the Kanji features went to MSXP98.ASM
  46.  
  47. ; Keyboard translator, by Joe R. Doupnik, Dec 1986
  48. ;  with contributions from David L. Knoell.
  49. ; For Generic keyboard reading (via DOS)
  50. ; edit history:
  51. ; Last edit 1 Jan 1988
  52. ; 1 Jan 1988 version 2.30
  53.  
  54.         include mssdef.h
  55.     include    msxp98.h
  56.  
  57.         public  keybd, dfkey, shkey, msuinit
  58.         public    ans_keystr
  59.         public    kbdlini, kbdlend
  60.  
  61. KEYCLICK_BIT    equ    4
  62.  
  63. ; NEC PC-9801 key related bios functions
  64. read_key    equ    0
  65. sense_key    equ    1
  66. sense_shift    equ    2
  67. ; sense_shift returns shift key state in AL
  68. ;          b5   b4   b3   b2   b1   b0
  69. ;       -+----+----+----+----+----+-----+
  70. ;        |****|CTRL|GRPH|KANA|CAPS|SHIFT|
  71. ;       -+----+----+----+----+----+-----+
  72.  
  73. ; NEC PC-9801 STOP and COPY key interrupt numbers
  74. INTNUM_COPY    equ    5
  75. INTNUM_STOP    equ    6
  76.  
  77. ; some definitions
  78.  
  79. maxkeys equ     256                     ; maximum number of key definitions
  80. maxstng equ     128                     ; maximum number of multi-char strings
  81. stbuflen equ    1024                    ; length of string buffer (bytes)
  82.  
  83. verb    equ     8000h                   ; dirlist flag: use verb action table
  84. strng   equ     4000h                   ; dirlist flag: use string action table
  85. scan    equ     100h                    ; keycode flag: code is scan not ascii
  86. braceop equ     7bh                     ; opening curly brace
  87. bracecl equ     7dh                     ; closing curly brace
  88.  
  89. data    segment public 'data'
  90.         extrn taklev:byte, comand:byte, flags:byte
  91.         extrn shkadr:word, stkadr:word, trans:byte
  92.                                                 ; system dependent references
  93.  
  94.     extrn    vt100_flags:byte        ; in MSXP98
  95.     extrn    keyin_dos:byte            ; in MSXP98
  96.     extrn vtmacname:word, vtmaclen:byte    ; external macro
  97.  
  98. ;;;     System Independent local storage
  99.  
  100. tranbuf db      132 dup (?)             ; 132 byte translator work buffer
  101. crlf    db      cr,lf,'$'
  102. dfhelp1 db    cr,lf,' Enter key',27h,'s identification as a character',cr,lf
  103.         db      '  or as its numerical equivalent \{b##} of ascii',cr,lf
  104.         db      '  or as its scan code \{b##}'
  105.         db      cr,lf,'  or as SCAN followed by its scan code',cr,lf
  106.         db      '    where b is O for octal, X for hex, or D for decimal'
  107.         db      ' (default).',cr,lf,'    Braces {} are optional.'
  108.         db      cr,lf,'    Follow the identification with the new definition.'
  109.         db      cr,lf,' or CLEAR to restore initial key settings.$'
  110. dfaskky db      cr,lf,' Push key to be defined: $'
  111. dfaskdf db      ' Enter new definition: ',0
  112. verbbad db      cr,lf,' No such verb',cr,lf,'$'
  113. strbad  db      cr,lf,' Not enough space for new string',cr,lf,'$'
  114. keyfull db      cr,lf,' No more space to define keys',cr,lf,'$'
  115. dfkoops db      cr,lf,' Opps! That is Kermit',27h,'s Escape Char.'
  116.         db      ' Translation is not permitted.',cr,lf,'$'
  117. shkmsg1 db      cr,lf,'Push key to be shown (? shows all): $'
  118. shkmsg2 db      ' decimal is defined as$'
  119. shkmsg3 db      cr,lf,'... more, push any key to continue ...$'
  120. kwarnmsg db     cr,lf,' Notice: this form of Set Key is obsolete$'
  121.  
  122. ascmsg  db      ' Ascii char: $'
  123. scanmsg db      ' Scan Code $'
  124. strngmsg db     ' String: $'
  125. verbmsg db      ' Verb: $'
  126. noxmsg  db      ' Self, no translation.$'
  127. fremsg  db      cr,lf,' Free space: $'
  128. kyfrdef db      ' key and $'
  129. stfrdef db      ' string definitions, $'
  130. stfrspc db      ' string characters.',cr,lf,'$'
  131.                                         ; translation tables
  132. keylist dw      maxkeys dup (0)         ; 16 bit keycodes, paralled by dirlist
  133. dirlist dw      maxkeys dup (0)         ; director {v+s} + {index | new char}
  134. sptable dw      maxstng dup (0)         ; list of asciiz string offsets
  135. stbuf   dw      stbuflen dup (0)        ; buffer for strings
  136. strmax  dw      stbuf                   ; first free byte in stbuf
  137. listptr dw      0                       ; item number for keylist and dirlist
  138. nkeys   dw      0                       ; number of actively defined keys
  139. keycode dw      0                       ; ascii/scan code for key
  140. kbtemp  dw      0                       ; scratch storage for translator
  141. brace   db      0                       ; brace detected flag byte
  142. oldform db      0                       ; old form Set Key, if non-zero
  143. verblen dw      0                       ; length of user's verb (work temp)
  144. kwcnt   dw      0                       ; number of keywords (work temp)
  145. msutake db      0                       ; if being run from take file or not
  146. twelve  dw      12d
  147. stringcnt dw    0            ; qty of string chars to be processed
  148. stringptr dw    0            ; address of next string char
  149.  
  150. ;;;     End System Independent Data Area
  151.  
  152. ;;;     System Dependent Data Area
  153.  
  154. ; old interrupt vectors for COPY and STOP key
  155. old_copy_ofs    dw    ?
  156. old_copy_sgm    dw    ?
  157. old_stop_ofs    dw    ?
  158. old_stop_sgm    dw    ?
  159.  
  160. intrkey        dw    0
  161. ;
  162. intkey_tab    dw    06000h        ; STOP
  163.         dw    06100h        ; COPY
  164.         dw    08000h        ; Shift+STOP
  165.         dw    08100h        ; Shift+COPY
  166.         dw    09000h        ; Ctrl+STOP
  167.         dw    09100h        ; Ctrl+COPY
  168. ;
  169.  
  170. ;       edit dfhelp2 to include nice list of verbs for this system.
  171. dfhelp2 db      cr,lf,' Enter either  \Kverb  for a Kermit action verb',cr,lf
  172.         db      ' or a replacement string  (single byte binary numbers are'
  173.         db      ' \{b##})',cr,lf,' or push Return to undefine a key, ^C to'
  174.         db      ' retain current definition.'
  175.         db      cr,lf,' Braces {} are optional, and strings maybe enclosed in'
  176.         db      ' them.',cr,lf,' Strings may not begin with the character'
  177.         db      ' combinations of  \k  or  \{k',cr,lf
  178.         db      '    (start with a { brace instead).',cr,lf,lf
  179.         db      ' Verbs are as follows. VT320 keys (arrows and keypad):',cr,lf
  180.         db   '   uparr, dnarr, lfarr, rtarr, kpminus, kpcoma, kpdot, kpenter,'
  181.         db      cr,lf
  182.         db   '   Gold (same as PF1), PF1, PF2, PF3, PF4, kp0, ... kp9'
  183.         db      cr,lf,'   decFind, decInsert, decRemove, decSelect, decPrev,'
  184.         db      ' decNext'
  185.         db      cr,lf,'   User Definable Keys decF6, ...decF14, decHelp,'
  186.         db      ' decDO, decF17, ...decF20'
  187.         db      cr,lf,' Kermit screen control and actions:',cr,lf
  188.         db   '   upscn, dnscn, homscn, endscn, upone, dnone, prtscn, dump,'
  189.         db      cr,lf
  190.         db   '   logoff, logon, termtype, reset, holdscrn, modeline, break,'
  191.         db      ' lbreak, nethold,'
  192.         db      cr,lf
  193.         db   '   hangup, null (send one), terminalR, terminalS, DOS, help,'
  194.         db   ' status, exit'
  195.         db      cr,lf,'$'
  196.  
  197.         ; Aliaskey: keys having aliases - same ascii code but more than one
  198.         ; scan code, as on auxillary keypads. Use just scan codes with these.
  199.         ; Alternative use: force ascii keys to report out just scan codes.
  200.         ; Table format: high byte = scan code, low byte = ascii code.
  201.         ; Contents are machine dependent.
  202. aliaskey    dw    001Bh        ; ESC
  203.         dw    0E08h        ; BS
  204.         dw    0F09h        ; TAB
  205.         dw    402Dh
  206.         dw    412Fh
  207.         dw    4237h
  208.         dw    4338h
  209.         dw    4439h
  210.         dw    452Ah
  211.         dw    4634h
  212.         dw    4735h
  213.         dw    4836h
  214.         dw    492Bh
  215.         dw    4A31h
  216.         dw    4B32h
  217.         dw    4C33h
  218.         dw    4D3Dh
  219.         dw    4E30h
  220.         dw    4F2Ch
  221.         dw    502Eh
  222.         dw    0A420h        ; SHIFT+space
  223.         dw    0B420h        ; CTRL+space
  224. aliaslen equ    ($-aliaskey) shr 1      ; number of words in aliaskey table
  225.  
  226. kverbs  db      66            ; number of table entries below
  227.         mkeyw   'uparr',uparrw        ; independent of ordering and case!
  228.         mkeyw   'dnarr',dnarrw        ; mkeyw 'name',procedure entry point
  229.         mkeyw    'lfarr',lfarrw
  230.         mkeyw    'rtarr',rtarrw
  231.         mkeyw    'gold',pf1
  232.         mkeyw    'pf1',pf1
  233.         mkeyw    'pf2',pf2
  234.         mkeyw    'pf3',pf3
  235.         mkeyw    'pf4',pf4
  236.         mkeyw    'kp0',kp0
  237.         mkeyw    'kp1',kp1
  238.         mkeyw    'kp2',kp2
  239.         mkeyw    'kp3',kp3
  240.         mkeyw    'kp4',kp4
  241.         mkeyw    'kp5',kp5
  242.         mkeyw    'kp6',kp6
  243.         mkeyw    'kp7',kp7
  244.         mkeyw    'kp8',kp8
  245.         mkeyw    'kp9',kp9
  246.         mkeyw    'kpminus',kpmins
  247.         mkeyw    'kpcoma',kpcoma
  248.         mkeyw    'kpenter',kpentr
  249.         mkeyw    'kpdot',kpdot
  250.         mkeyw   'decF6',decf6
  251.         mkeyw   'decF7',decf7
  252.         mkeyw   'decF8',decf8
  253.         mkeyw   'decF9',decf9
  254.         mkeyw   'decF10',decf10
  255.         mkeyw   'decF11',decf11
  256.         mkeyw   'decF12',decf12
  257.         mkeyw   'decF13',decf13
  258.         mkeyw   'decF14',decf14
  259.         mkeyw   'decHelp',dechelp
  260.         mkeyw   'decDo',decdo
  261.         mkeyw   'decF17',decf17
  262.         mkeyw   'decF18',decf18
  263.         mkeyw   'decF19',decf19
  264.         mkeyw   'decF20',decf20
  265.         mkeyw   'decFind',decfind
  266.         mkeyw   'decInsert',decinsert
  267.         mkeyw   'decRemove',decremove
  268.         mkeyw   'decSelect',decselect
  269.         mkeyw   'decPrev',decprev
  270.         mkeyw   'decNext',decnext
  271.         mkeyw    'termtype',vtchg
  272.         mkeyw    'reset',vtreset
  273.         mkeyw    'prtscn',prtscn
  274.         mkeyw    'trnprs',trnprs
  275.     mkeyw    'modeline',trnmod
  276.         mkeyw    'break',sendbr
  277.         mkeyw   'hangup',chang
  278.         mkeyw   'null',snull
  279.         mkeyw   'help',cquery
  280.         mkeyw   'status',cstatus
  281.         mkeyw   'exit',cquit
  282.     mkeyw    'terminalR',vtrmac
  283.     mkeyw    'terminalS',vtsmac
  284.         mkeyw   'DOS',kdos
  285.         mkeyw   'logoff',klogof
  286.         mkeyw   'logon',klogon
  287.     mkeyw    'upone',upone
  288.     mkeyw    'dnone',dnone
  289.     mkeyw    'upscn',upscn
  290.     mkeyw    'dnscn',dnscn
  291.     mkeyw    'gupone',gupone
  292.     mkeyw    'gdnone',gdnone
  293.                                 ; Initialization data.
  294. kbdinlst equ    this byte     ; Kermit PC98 initialization time keyboard setup
  295.     mkeyw    '\x1b',256    ; ESC key sends ESC
  296.         mkeyw   '\x7f',270      ; BS key sends delete
  297.         mkeyw    '\9',271    ; TAB key sends TAB
  298.     mkeyw    '\8',313    ; DEL key sends backspace
  299.     mkeyw    '\kuparr',314    ; Up arrow key
  300.     mkeyw    '\klfarr',315    ; Left arrow key
  301.     mkeyw    '\krtarr',316    ; Right arrow key
  302.     mkeyw    '\kdnarr',317    ; Down arrow key send <ESC>[B
  303.     mkeyw    '\kpf1',318    ; HOME/CLR
  304.     mkeyw    '\kpf2',319    ; HELP
  305.     mkeyw    '\kpf3',320    ; keypad minus
  306.     mkeyw    '\kpf4',321    ; keypad slash
  307.     mkeyw    '\kkp7',322    ; keypad 7
  308.     mkeyw    '\kkp8',323    ; keypad 8
  309.     mkeyw    '\kkp9',324    ; keypad 9
  310.     mkeyw    '\kkpminus',325    ; keypad *
  311.     mkeyw    '\kkp4',326    ; keypad 4
  312.     mkeyw    '\kkp5',327    ; keypad 5
  313.     mkeyw    '\kkp6',328    ; keypad 6
  314.     mkeyw    '\kkpcoma',329    ; keypad +
  315.     mkeyw    '\kkp1',330    ; keypad 1
  316.     mkeyw    '\kkp2',331    ; keypad 2
  317.     mkeyw    '\kkp3',332    ; keypad 3
  318.     mkeyw    '\kkpenter',333    ; keypad =
  319.     mkeyw    '\kkp0',334    ; keypad 0
  320.     mkeyw    '\kkp0',335    ; keypad ,
  321.     mkeyw    '\kkpdot',336    ; keypad .
  322.     mkeyw    '\kdnone',310    ; ROLL UP
  323.     mkeyw    '\kupone',311    ; ROLL DOWN
  324.     mkeyw    '\kexit',352    ; STOP
  325.     mkeyw    '\kprtscn',353    ; COPY
  326.     mkeyw    '\kbreak',384    ; shift+STOP
  327.     mkeyw    '\ktrnprs',385    ; shift+COPY
  328.     mkeyw    '\x20',420    ; shift+SPACE
  329.     mkeyw    '\knull',436    ; ctrl+SPACE
  330.     mkeyw    '\kdnscn',438    ; ctrl+ROLL UP
  331.     mkeyw    '\kupscn',439    ; ctrl+ROLL DOWN
  332.     mkeyw    '\x1b$B',KI_CODE    ; KI virtual key
  333.     mkeyw    '\x1b(J',KO_CODE    ; KO virtual key
  334.         dw      0               ; end of table marker
  335.  
  336. keypadnum    dw    452Ah    ; *
  337.         dw    492Bh    ; +
  338.         dw    4F2Ch    ; ,
  339.         dw    402Dh    ; -
  340.         dw    502Eh    ; .
  341.         dw    412Fh    ; /
  342.         dw    4E30h    ; 0
  343.         dw    4A31h    ; 1
  344.         dw    4B32h    ; 2
  345.         dw    4C33h    ; 3
  346.         dw    4634h    ; 4
  347.         dw    4735h    ; 5
  348.         dw    4836h    ; 6
  349.         dw    4237h    ; 7
  350.         dw    4338h    ; 8
  351.         dw    4439h    ; 9
  352.         dw    273Ah
  353.         dw    263Bh
  354.         dw    302Ch
  355.         dw    4D3Dh    ; =
  356.  
  357. keypadgrp    dw    2008h    ; *
  358.         dw    0209h    ; +
  359.         dw    8009h    ; ,
  360.         dw    0108h    ; -
  361.         dw    010Ah    ; .
  362.         dw    0208h    ; /
  363.         dw    4009h    ; 0
  364.         dw    0409h    ; 1
  365.         dw    0809h    ; 2
  366.         dw    1009h    ; 3
  367.         dw    4008h    ; 4
  368.         dw    8008h    ; 5
  369.         dw    0109h    ; 6
  370.         dw    0408h    ; 7
  371.         dw    0808h    ; 8
  372.         dw    1008h    ; 9
  373.         dw    000Ah
  374.         dw    000Ah
  375.         dw    000Ah
  376.         dw    2009h    ; =
  377.  
  378.  
  379. data    ends
  380.  
  381. ;                       Documentation
  382. ;Translating a key:
  383. ;   The translator is called to obtain keyboard input; it sends characters to
  384. ; the serial port through standard controlled echo procedures or invokes
  385. ; named procedures. It returns carry clear when its operation is completed
  386. ; for normal actions and carry set when Connect mode must be exited. When
  387. ; Connect mode is exited the just read char should be passed in Kbdflg
  388. ; to msster.asm for invoking actions such as Status, send a break,
  389. ; quit connect mode; system dependent procedure Term is responsible for this.
  390. ;
  391. ;  Principal procedures are -
  392. ;       msuinit         Initializes keyboard translator in this file when
  393. ;                       Kermit first begins. Installs dfkey and shkey as the
  394. ;                       procedures used for Set Key and Show Key. Sys Indep.
  395. ;                       Called from msx or msy init procs. System Independent.
  396. ;       keybd           Performs the translation, outputs chars to the serial
  397. ;                       port or invokes a Kermit action routine. Sys Indep.
  398. ;       dfkey           Defines a key's translation. Reads command line
  399. ;                       via Kermit's command parser comnd. System Independent.
  400. ;       shkey           Shows translation of a key. Requests user to push
  401. ;                       selected key. System Independent.
  402. ;
  403. ;       kbdinit         optional. Initializes the translation tables when
  404. ;                       Kermit starts up. Called by msuinit. System Dependent.
  405. ;       getkey          Performs the keyboard read and returns results in
  406. ;                       a standardized system independent format. Sys Depend.
  407. ;       postkey         called by active translator after obtaining a keycode.
  408. ;                       Used to provide extra local actions (keyclick) only
  409. ;                       in Connect mode (not during Set/Show key commands).
  410. ;                       Called by keybd. System dependent.
  411. ; Supporting system independent procedures are -
  412. ; shkfre (show string free space), tstkeyw (finds user's keyword in the verb
  413. ; table), insertst (insert string in buffer), remstr (delete string in buffer).
  414. ;
  415. ;   System dependent procedure Getkey reads a keycode (usually via a Bios
  416. ; call). On IBM compatible machines this yields <ah=scan code, al=ascii>
  417. ; for ordinary keys, or <ah=scan code, al=0> for special keys such as F1,
  418. ; or <ah=0, al=###> when Alt### is used.
  419. ; For any system, the canonical output form is the key's code in Keycode.
  420. ; Place the ascii code (or scan code if none) in byte Keycode and ancillary
  421. ; info (shift states plus marker bit for scan codes) in byte Keycode + 1.
  422. ;
  423. ;   Table Aliaskey is a list of scan code/ascii codes for keys which appear
  424. ; more than once on a keyboard. This list is examined to distinguish such
  425. ; aliased keys (those on an auxillary keypad) from an ordinary ascii key,
  426. ; and the aliased key is then referenced by its scan code rather than by
  427. ; the ordinary ascii code. Aliaskey is machine and keyboard dependent.
  428. ;
  429. ;    Procedure Keybd calls Getkey for the Keycode, checks list of translatable
  430. ; keys Keylist, and then either sends an ascii string (one or more characters)
  431. ; or invokes a Kermit action verb. List Dirlist indicates what kind of
  432. ; translation to do. Keybd is system independent but may contain system
  433. ; dependent special actions such as echoing keyclicks. Keybd calls system
  434. ; dependent procedure Postkey just after calling getkey so local actions
  435. ; such as keyclicks can be activated only during Connect mode operations.
  436. ;
  437. ;    Keylist is a packed but unordered list of 16 bit keycodes which need
  438. ; translation. The lower order byte holds a key code (ascii char or scan code)
  439. ; while the high byte holds a scan code marker bit (0 if ascii code in low
  440. ; byte) plus any ancillary keyboard information such as Control/Shift/Alt/Meta
  441. ; keys being held down; these are of use in Show Key presentations.
  442. ;    Dirlist parallels Keylist to provide the kind of translation, verb or
  443. ; string, in the two highest bits with the other bits holding either
  444. ; a single new replacement character or the item number in lists of verbs
  445. ; or strings. If neither verb nor strng type bits are set in a dirlist
  446. ; word then the translation is a single new character held in the lower
  447. ; eight bits of that dirlist word.
  448. ;
  449. ;    The number of key translations is assembly constant Maxkeys (def 128).
  450. ;    The maximum number of strings is assembly constant Maxstngs (def 64).
  451. ;    The maximum number of verbs is 256 and is set by building table Kverbs.
  452. ;
  453. ;   For verbs, use the Item number from the Director table Dirlist to select
  454. ; a procedure offset from the structured list Kverbs and jump to that offset.
  455. ; Most verb procedures return carry clear to stay within Connect mode.
  456. ; Verbs requiring exiting Connect mode return carry set and may set byte
  457. ; Kbdflg to a char code which will be read by msster.asm for activating a
  458. ; transient Kermit action such as send a break (Kbdflg = 'b').
  459. ; Kbdflg is stored in msster.asm (as zero initially, meaning ignore it).
  460. ; Action verb procedures are normally located in a system dependent file.
  461. ;
  462. ;   For multi-char strings, use Item number from Director table Dirlist to
  463. ; select a pointer to a string. The list of string pointers is Sptable
  464. ; (string pointer table) which holds the offset in the data segment of the
  465. ; strings stored in buffer Stbuf. In stbuf strings are held as: one byte of
  466. ; length of following text and then the text itself (permits embedded nulls).
  467. ;  Use Chrout to send each string character, and finally return from Keybd
  468. ; with carry clear.
  469. ;
  470. ;   For single character replacements obtain the new character from the lower
  471. ; order byte of Director table Dirlist. If the character is Kermit's present
  472. ; escape character return from Keybd carry set to leave connect mode.
  473. ; Otherwise, send the character via Chrout and return from Keybd carry clear.
  474.  
  475. ; Keylist table format:
  476. ;    7 bits   1 bit   8 bits
  477. ; +----------+----+------------+ scan bit = 1 if key's code is non-ascii
  478. ; | aux info |scan| key's code | aux info = system dependent, used only to
  479. ; +----------+----+------------+            help identify key
  480. ;
  481. ; Dirlist table format            v s   meaning
  482. ;   1   1      14 bits            0 0   copy out one byte translation
  483. ; +---+---+--------------------+  1 0   copy out multi-char string number Item
  484. ; | v | s | item # or new char |  0 1   do action verb number Item
  485. ; +---+---+--------------------+  1 1   (not used)
  486. ;
  487. ; Table kverbs is organized by macro mkeyw as -
  488. ;       kverbs  db      number of table entries
  489. ;       (each entry is in the form below:)
  490. ;               db      number of bytes in verbname
  491. ;               db      'verbname'              variable length
  492. ;               db      '$'                     for printing
  493. ;               dw      value                   offset of procedure
  494. ;
  495. ;
  496. ;   Dfkey defines a key to be itself (undefines it) or a single replacement
  497. ; character or a character string or a Kermit action verb. Dfkey requires
  498. ; a command line so that it may be invoked by Take files but can be forced
  499. ; to prompt an interactive user to push a key. Syntax is discussed below.
  500. ; Note that redefined keys have their old definitions cleared so that
  501. ; old string space is reclaimed automatically.
  502. ;
  503. ;   Shkey displays a key's definition and the user is asked to push the
  504. ; selected key. The free space for strings is always shown afterward. See
  505. ; below for syntax.
  506. ;
  507. ;   Kbdinit is an optional routine called when Kermit starts up. It fills in
  508. ; the translation tables with desirable default values to save having to
  509. ; use long mskermit.ini files. The default values are stored in a structured
  510. ; table similar to (but not the same as) Dfkey's command lines; the keycode
  511. ; values are preset by hand to 16 bit numbers.
  512.  
  513. ;Defining a key:
  514. ; Command is SET KEY <key ident><whitespace><definition>
  515. ;
  516. ; <key ident> is
  517. ;               a single ordinary ascii char or
  518. ;               the numerical equivalent of an ascii char or
  519. ;               a Scan Code written as a number or
  520. ;               keyword SCAN followed by a number.
  521. ;               ?       Displays help message.
  522. ;       Numbers and Binary codes are of the form
  523. ;               \123    a decimal number
  524. ;               \o456   an octal number         base letters o, d, x can be
  525. ;               \d213   a decimal number        upper or lower case
  526. ;               \x0d    a hex number
  527. ;               \{b###}  braces around above material following slash.
  528. ;
  529. ; <whitespace> is one or more spaces and or tabs.
  530. ;
  531. ; <definition> is
  532. ;       missing altogether which "undefines" a key.
  533. ;       \Kverb          for a Kermit action verb; upper or lower case K is ok
  534. ;       \{Kverb}        ditto. Verb is the name of an action verb.
  535. ;       text            a string with allowed embedded whitespace and embedded
  536. ;                       binary chars as above. This kind of string may not
  537. ;                       commence with sequences \K or \{K; use braces below.
  538. ;       {text}          string confined to material within but excluding
  539. ;                       the braces. Note, where the number of opening braces
  540. ;                       exceeds the number of closing braces the end of line
  541. ;                       terminates the string: {ab{}{{c}d ==> ab{}{{c}d
  542. ;                       but  {ab}{{c}d ==> ab.
  543. ;       ?               Displays help message and lists all action verbs.
  544. ;
  545. ;       If Set Key is given interactively, as opposed to within a Take
  546. ;       file, the system will prompt for inputs if none is on the command
  547. ;       line. The response to Push key to be defined cannot be edited.
  548. ;
  549. ;       Text which reduces to a single replacement character is put into a
  550. ;       table separate from the multi-character strings (maxstng of these).
  551. ;       A key may be translated into any single 8 bit code.
  552. ;
  553. ;       Comments can follow a Kermit action verb or a braced string; no
  554. ;       semicolon is required since all are stripped out by the Take file
  555. ;       reader before the defining text is seen by SET KEY.
  556. ;
  557. ;       The current Kermit escape character cannot be translated without
  558. ;       subtrafuge.
  559. ;
  560. ;       Examples:
  561. ;               Set Key q z
  562. ;                               makes key q send character z
  563. ;               Set Key \7 \27[0m
  564. ;                               makes key Control G send the four byte
  565. ;                               string  ESC [ 0 m
  566. ;               Set Key q
  567. ;                               undefines key q so it sends itself (q) again.
  568. ;               Set Key \2349 \kexit
  569. ;                               defines IBM Alt-X to invoke the leave connect
  570. ;                               mode verb "exit" (Kermit's escape-char ^] C).
  571. ;               Set Key \x0c Login \{x0d}myname\{x0d}mypass\x0d
  572. ;                               defines Control L to send the string
  573. ;                               Login <cr>myname<cr>mypass<cr>
  574. ;
  575. ; Alternative Set Key syntax for backward compatibility with previous versions
  576. ;       The same forms as above except the key identification number must
  577. ;       be decimal and must Not have a leading backslash. Example:
  578. ;       Set Key Scan 59 This is the F1 key
  579. ;
  580. ;       If the definition is omitted it may be placed on the following line;
  581. ;       if that line is also empty the key is undefined (defined as Self).
  582. ;       A warning message about obsolete syntax will be given followed by
  583. ;       the key's modern numerical value and new definition. Only "special"
  584. ;       keys (those not producing ascii codes) are compatible with this
  585. ;       translator.
  586. ;
  587. ;Showing a key:
  588. ; Command is SHOW KEY <cr>
  589. ; System prompts user to press a key and shows the definition plus the
  590. ; free space for strings. Query response results in showing all definitions.
  591. ;                       End Documentation
  592.  
  593. code    segment public 'code'
  594.                 ; system independent external items
  595.         extrn   comnd:near, prompt:near                 ; in msscmd
  596.         extrn   strlen:near                             ; in mssfil
  597.         extrn   cnvlin:near, katoi:near, decout:near    ; in msster
  598.                 ; system dependent external items
  599.                 ; these are system dependent action verbs, in msxgen
  600.         extrn   beep:near, trnprs:near, sendbr:near
  601.         extrn   chrout:near, cstatus:near, cquit:near, cquery:near
  602.         extrn   klogon:near, klogof:near, kdos:near, snull:near, chang:near
  603.         extrn    trnmod:near
  604.  
  605.         extrn    pf1:near, pf2:near, pf3:near, pf4:near
  606.         extrn    kp0:near, kp1:near, kp2:near, kp3:near, kp4:near
  607.         extrn    kp5:near, kp6:near, kp7:near, kp8:near, kp9:near
  608.         extrn    kpmins:near, kpcoma:near, kpentr:near, kpdot:near
  609.         extrn    uparrw:near, dnarrw:near, lfarrw:near, rtarrw:near
  610.         extrn    decf6:near, decf7:near, decf8:near, decf9:near, decf10:near
  611.         extrn    decf11:near, decf12:near, decf13:near, decf14:near
  612.     extrn    dechelp:near, decdo:near
  613.     extrn    decf17:near, decf18:near, decf19:near, decf20:near
  614.     extrn    decfind:near, decinsert:near, decremove:near, decselect:near
  615.     extrn    decprev:near, decnext:near
  616.         extrn    keyinchg:near
  617.         extrn    vtchg:near, vtreset:near
  618.     extrn    upone:near, dnone:near, upscn:near, dnscn:near
  619.     extrn    gupone:near, gdnone:near
  620.     extrn    prtscn:near
  621.     extrn    vtrmac:near, vtsmac:near, extmacro:near
  622.  
  623.      extrn    s2jis:near, is_kanji1:near
  624.  
  625.         assume  cs:code, ds:data, es:data
  626.  
  627. ; Begin system independent Keyboard Translator code
  628.  
  629. ; MSUINIT performs Kermit startup initialization for this file.
  630. ; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
  631. ; are not initialized here then the older Set/Show Key procedures are called.
  632. MSUINIT PROC    NEAR                    ; call from msx/msy init code
  633.         call    kbdinit                 ; optional: init translator tables
  634.         mov     shkadr,offset shkey     ; declare keyboard translator present
  635.         mov     stkadr,offset dfkey     ; via Show and Set Key proc addresses
  636.         ret
  637. MSUINIT ENDP
  638.  
  639. ; Call Keybd to read a keyboard char (just returns carry clear if none) and
  640. ; 1) send the replacement string (or original char if not translated)
  641. ;    out the serial port, or
  642. ; 2) execute a Kermit action verb.
  643. ; Returns carry set if Connect mode is to be exited, else carry clear.
  644. ; Modifies registers ax and bx.
  645. KEYBD   PROC    NEAR                    ; active translator
  646.     cmp    stringcnt,0        ; any leftover string chars?
  647.     je    keybd0            ; e = no
  648.     jmp    keyst2            ; yes, finish string
  649. keybd0:    call    getkey            ; read keyboard
  650.     jnc    keybd1            ; nc = data available
  651.     jmp    keybdx            ; else just return carry clear
  652. keybd1:    call    postkey            ; call system dependent post processor
  653.         cmp     nkeys,0                 ; is number of keys defined = 0?
  654.         jz      keybd3                  ; z = none defined
  655.         push    di                      ; search keylist for this keycode
  656.         push    cx                      ; save some registers
  657.         push    es
  658.         mov     di,offset keylist       ; list of defined keycode words
  659.         mov     ax,keycode              ; present keycode
  660.         mov     cx,nkeys                ; number of words to examine
  661.         push    ds
  662.         pop     es                      ; make es:di point to data segment
  663.         cld
  664.         repne   scasw                   ; find keycode in list
  665.         pop     es                      ; restore regs
  666.         pop     cx
  667.         je      keybd1b                 ; e = found, work with present di
  668.         pop     di                      ; restore original di
  669.         test    keycode,scan            ; is this a scan code?
  670.         jz      keybd3                  ; z = no, it's ascii, use al as char
  671.         call    beep                    ; say key is a dead one
  672.         clc
  673.         ret                             ; and exit with no action
  674.  
  675. keybd1b:sub     di,2                    ; correct for auto increment
  676.         sub     di,offset keylist       ; subtract start of list ==> listptr
  677.         mov     ax,dirlist[di]          ; ax = contents of director word
  678.         pop     di                      ; restore original di
  679.                                         ; dispatch on Director code
  680.         test    ax,verb                 ; verb only?
  681.         jnz     keyvb                   ; e = yes
  682.         test    ax,strng                ; multi-char string only?
  683.         jnz     keyst                   ; e = yes, else single char & no xlat.
  684.                                         ;
  685.                                         ; do single CHAR output (char in al)
  686. keybd3: cmp     al,trans.escchr         ; Kermit's escape char?
  687.         je      keybd3a                 ; e = yes, handle separately
  688. ;;;    call    xltkey            ; do character set translation
  689.         call    chrout                  ; transmit the char
  690.         clc                             ; return success
  691.         ret
  692. keybd3a:stc                             ; set carry for jump to Quit
  693.         ret
  694.  
  695. keyvb:  and     ax,not(verb+strng)      ; VERB (ax=index, remove type bits)
  696.         mov     bx,offset kverbs        ; start of verb table
  697.         cmp     al,byte ptr [bx]        ; index > number of entries?
  698.         jae     keybdx                  ; ae = illegal, indices start at 0
  699.         inc     bx                      ; bx points to first entry
  700.         push    cx                      ; save reg
  701.         mov     cx,ax                   ; save the index in cx
  702.         inc     cx                      ; counter, indices start at 0
  703. keyvb1: mov     al,byte ptr [bx]        ; cnt value
  704.         xor     ah,ah
  705.         add     ax,4                    ; skip text and '?' and value word
  706.         add     bx,ax                   ; look at next slot
  707.         loop    keyvb1                  ; walk to correct slot
  708.         sub     bx,2                    ; backup to value field
  709.     pop     cx                      ; restore reg
  710.         mov     bx,[bx]                 ; get value field of this slot
  711.         cmp     bx,0                    ; jump address defined?
  712.         je      keybdx                  ; e = no, skip the action
  713.         jmp     bx                      ; perform the function
  714.  
  715. keyst:    and    ax,not(verb+strng)    ; STRING (ax=index, remove type bits)
  716.     shl    ax,1            ; convert to word index
  717.     push    si            ; save working reg
  718.     mov    si,ax            ; word subscript in table
  719.     mov    si,sptable[si]        ; memory offset of selected string
  720.     xor    cx,cx            ; init string length to null
  721.     cmp    si,0            ; is there a string pointer present?
  722.     je    keyst1            ; e = no, skip operation
  723.     cld                ; scan forward
  724.     mov    cl,byte ptr [si]    ; get string length byte
  725.     inc    si
  726. keyst1:    mov    stringcnt,cx
  727.     mov    stringptr,si
  728.     pop    si
  729.     jcxz    keybdx            ; z = null length
  730.  
  731. keyst2:    push    si
  732.     mov    si,stringptr        ; pointer to next string char
  733.     cld
  734.     lodsb                ; get new string char into al
  735.     pop    si
  736.     dec    stringcnt        ; string chars remaining
  737.     inc    stringptr
  738.     call    keysv            ; scan for embedded verbs
  739.     jc    keyst4            ; c = not found, al has string char
  740.     jmp    bx            ; perform the verb (bx = address)
  741. keyst4:
  742. ;;;    call    xltkey            ; do character set translation
  743.     cmp    stringcnt,0        ; last character?
  744.     je    keyst5            ; e = yes, stop grouping for nets
  745. keyst5:    jmp    chrout            ; send out the char in al
  746.  
  747. keybdx:    clc                ; return success (nothing to do)
  748.     ret
  749. KEYBD   ENDP
  750.  
  751.  
  752. ; Scan for keyboard verbs embedded in outgoing string. If found update
  753. ; string pointer and count to just beyond the verb and return action routine
  754. ; address in bx with carry clear. If failure return carry set and no change.
  755. ; Can invoke external procedure EXTMACRO if the verb is not known here.
  756.  
  757. keysv    proc    near
  758.     push    ax
  759.     push    si
  760.     push    di
  761.     cmp    al,'\'            ; escape?
  762.     jne    keysv7            ; ne = no
  763.     mov    cx,stringcnt        ; chars remaining
  764.     mov    si,stringptr        ; address of next char to read
  765.     mov    brace,0            ; assume not using braces
  766.     cmp    byte ptr [si],braceop    ; starts with \{?
  767.     jne    keysv1            ; ne = no
  768.     inc    si            ; skip the opening brace
  769.     dec    cx
  770.     mov    brace,bracecl        ; expect closing brace
  771. keysv1:    cmp    byte ptr [si],'K'    ; starts with \{K or \K?
  772.     je    keysv2            ; e = yes
  773.     cmp    byte ptr [si],'k'    ; starts as \{k or \k?
  774.     jne    keysv7            ; ne = no, then it's a string
  775. keysv2:    inc    si            ; yes, skip the K too
  776.     dec    cx
  777.     mov    di,offset tranbuf    ; copy verb name to this work buffer
  778.     xor    ax,ax
  779.     mov    [di],ax            ; init the buffer to empty
  780. keysv3:    cld
  781.     jcxz    keysv4            ; z = no more string chars
  782.     lodsb                ; scan til closing brace or w/s or end
  783.     dec    cx
  784.     cmp    al,brace        ; closing brace?
  785.     je    keysv4            ; e = yes
  786.     cmp    al,spc            ; white space or control char?
  787.     jbe    keysv3            ; be = yes
  788.     mov    [di],ax            ; copy to tranbuf and terminate
  789.     inc    di
  790.     jmp    short keysv3
  791. keysv4:    push    si            ; save input reading position
  792.     mov    si,offset tranbuf    ; where verb starts (needs si)
  793.     call    tstkeyw            ; find keyword, bx = action routine
  794.     pop    si
  795.     jnc    keysv4a            ; nc = found the verb
  796.     call    keysv8            ; invoke EXTMACRO worker for unknown
  797.     jc    keysv7            ; carry = no verb to operate upon
  798. keysv4a:cmp    brace,0            ; need to end on a brace?
  799.     je    keysv6            ; e = no
  800.     dec    si            ; break position
  801.     inc    cx
  802.     cld
  803. keysv5:    jcxz    keysv6            ; z = no more string characters
  804.     lodsb                ; read string char
  805.     dec    cx
  806.     cmp    al,brace        ; the brace?
  807.     jne    keysv5            ; ne = no, repeat until it is found
  808. keysv6:    mov    stringptr,si        ; where we finished+1
  809.     mov    stringcnt,cx        ; new count of remaining chars
  810.     pop    di
  811.     pop    si            ; original si, starting place
  812.     pop    ax            ; original ax
  813.     clc
  814.     ret
  815. keysv7:    pop    di            ; verb not found
  816.     pop    si
  817.     pop    ax
  818.     stc
  819.     ret
  820. ; Worker. Unknown verb name as string {\kverb} or {\k{verb}}. Use EXTMACRO
  821. ; procedure (in msyibm typically), point to verb name with vtmacname, length
  822. ; of it in byte vtmaclen, address of EXTMACRO to BX. Upper case the verb.
  823. ; Enter with tranbuf holding the verb, asciiz, without \K and braces.
  824. ; Returns BX set to EXTMACRO proc, vtmacname pointing to verb (uppercased)
  825. ; and vtmaclen holding the length of verb.
  826. keysv8:    mov    bx,offset extmacro    ; use this external macro pointer
  827.     mov    vtmacname,offset tranbuf; select extmacro procedure address
  828.     mov    dx,offset tranbuf    ; point to name for extmacro
  829.     push    cx
  830.     call    strlen            ; get its length
  831.     mov    vtmaclen,cl        ; length for extmacro
  832.     jcxz    keysv11            ; z = none
  833.     push    si            ; convert verb name to upper case
  834.     mov    si,dx            ; verb, without leading \K stuff
  835.     cld
  836. keysv9:    lodsb                ; read a name byte
  837.     cmp    al,'a'            ; before lower case?
  838.     jb    keysv10            ; e = yes
  839.     cmp    al,'z'            ; above lower case?
  840.     ja    keysv10            ; a = yes
  841.     and    al,not 20h        ; convert to upper case
  842.     mov    [si-1],al        ; put it back
  843. keysv10:loop    keysv9            ; do all bytes, asciiz
  844.     pop    si
  845.     pop    cx
  846.     clc                ; carry clear = ready to execute
  847.     ret
  848. keysv11:stc                ; carry set = no verb, do nothing
  849.     pop    cx
  850.     ret
  851. keysv    endp
  852.  
  853. ; SET KEY - define a key   (procedure dfkey)
  854. ; SET KEY <key ident><whitespace><new meaning>
  855. ; Call from Kermit level. Returns as ret if failure or as rskp if success.
  856. ;
  857. DFKEY   PROC    NEAR                    ; define a key as a verb or a string
  858.         mov     keycode,0               ; clear keycode
  859.         mov     oldform,0               ; say no old form Set Key yet
  860.         mov     dx,offset tranbuf       ; our work space
  861.         mov     word ptr tranbuf,0      ; insert terminator
  862.         mov     bx,offset dfhelp1       ; first help message
  863.         mov     ah,cmword               ; parse a word
  864.         call    comnd                   ; get key code or original ascii char
  865.     mov    al,taklev        ; reading from Take file
  866.         mov     msutake,al              ; save here
  867.         or      ah,ah                   ; any text given?
  868.         jnz     dfkey12                 ; nz = yes, so don't consider prompts
  869.                                         ; interactive key request
  870.         cmp     taklev,0                ; in a Take file?
  871.         je      dfkey10                 ; e = no, prompt for keystroke
  872.         jmp     dfkey0                  ;  else say bad syntax
  873. dfkey10:mov     ah,prstr
  874.         mov     dx,offset dfaskky       ; ask for key to be pressed
  875.         int     dos
  876. dfkey11:call    getkey                  ; read key ident from keyboard
  877.         jc      dfkey11                 ; c = no response, wait for keystroke
  878.         mov     ah,prstr                ; display cr/lf
  879.         mov     dx,offset crlf
  880.         int     dos
  881.         call    shkey0                  ; show current definition (in SHKEY)
  882.         jmp     dfkey1e                 ; prompt for and process definition
  883.  
  884. dfkey12:                                ; Look for word SCAN and ignore it
  885.         mov     dx,word ptr tranbuf     ; get first two characters
  886.         or      dx,2020h                ; map upper to lower case
  887.         cmp     dx,'cs'                 ; first two letters of word "scan"?
  888.         je      dfkey                   ; e = yes, skip the word
  889.         cmp     dx,'lc'                 ; first two letters of word "clear"?
  890.     je    dfkey15            ; e = yes, reinit keyboard
  891. dfkey13:
  892.     cmp    dx,'ik'            ; KI:Kanji-in virtual key? [HF01]
  893.     jne    dfkey14            ; ne = no. [HF01]
  894.     mov    keycode,KI_code        ; store keycode [HF01]
  895.     jmp    dfkey1b            ; go get definition [HF01]
  896. dfkey14:
  897.     cmp    dx,'ok'            ; KO:Kanji-out virtual key? [HF01]
  898.     jne    dfkey14a        ; ne = no. [HF01]
  899.     mov    keycode,KO_code        ; store keycode [HF01]
  900.     jmp    dfkey1b            ; go get definition [HF01]
  901. dfkey14a:
  902.         cmp     ah,1                    ; number of characters received
  903.         ja      dfkey1                  ; a = more than one, decode
  904.         mov     ah,byte ptr tranbuf     ; get the single char
  905.         mov     byte ptr keycode,ah     ; store as ascii keycode
  906.         jmp     dfkey1b                 ; go get definition
  907.  
  908. dfkey15:mov    ah,cmeol
  909.     call    comnd            ; confirm request before proceeding
  910.     jnc    dfkeyc            ; nc = success
  911.     ret                ; failure
  912.  
  913. dfkey0:    mov    dx,offset dfhelp1    ; say bad definition command
  914.     mov    ah,prstr
  915.     int    dos
  916.     stc                ; failure
  917.     ret
  918.  
  919. dfkeyc:                                 ; CLEAR key defs, restore startup defs
  920.         mov     cx,maxkeys              ; size of keycode tables
  921.         push    es                      ; save register
  922.         push    ds
  923.         pop     es                      ; make es point to data segment
  924.     xor    ax,ax            ; null, value to be stored
  925.         mov     di,offset dirlist       ; director table
  926.         cld
  927.         rep     stosw                   ; clear it
  928.         mov     cx,maxkeys
  929.         mov     di,offset keylist       ; keycode table
  930.         rep     stosw                   ; clear it
  931.         mov     cx,maxstng
  932.         mov     di,offset sptable       ; string pointer table
  933.         rep     stosw                   ; clear it
  934.         pop     es                      ; recover register
  935.     mov    strmax,offset stbuf    ; clear string buffer, free space ptr
  936.     mov    stbuf,0            ; first element of buffer 
  937.     mov    nkeys,0            ; clear number of defined keys
  938.     call    msuinit            ; restore startup definitions
  939.     clc                ; success
  940.     ret
  941.                                         ; Multi-char key identification
  942. dfkey1: mov     si,offset tranbuf       ; point to key ident text
  943.         cmp     byte ptr [si],'0'       ; is first character numeric?
  944.         jb      dfkey1a                 ; b = no
  945.         cmp     byte ptr [si],'9'       ; in numbers?
  946.         ja      dfkey1a                 ; a = no
  947.         mov     keycode,scan            ; setup keycode for scan value
  948.         mov     dx,si                   ; get length of string in cx
  949.         call    strlen
  950.         push    ds
  951.         pop     es                      ; make es point to data segment
  952.         push    si
  953.         add     si,cx                   ; point at string terminator
  954.         mov     di,si
  955.         inc     di                      ; place to store string (1 byte later)
  956.         inc     cx                      ; include null terminator
  957.         std                             ; work backward
  958.         rep     movsb                   ; move string one place later
  959.         cld
  960.         pop     si
  961.         mov     byte ptr [si],'\'       ; make ascii digits into \nnn form
  962.         mov     oldform,0ffh            ; set old form flag
  963.         mov     dx,offset kwarnmsg      ; tell user this is old form
  964.         mov     ah,prstr
  965.         int     dos
  966. dfkey1a:call    katoi                   ; convert ascii number to binary in ax
  967.         jc      dfkey0                  ; c = no number converted
  968.         or      keycode,ax              ; store in keycode
  969.  
  970. dfkey1b:                                ; Get Definition proper
  971.         test    oldform,0ffh            ; old form Set Key active?
  972.         jz      dfkey1f                 ; z = no
  973.         mov     bx,offset tranbuf       ; get new definition on main cmd line
  974.         mov     word ptr [bx],0         ; insert terminator
  975.         mov     dx,offset dfhelp2       ; help for definition of key
  976.         mov     ah,cmline               ; read rest of line into tranbuf
  977.     call    comnd            ; allow null definitions
  978.         or      ah,ah                   ; char count zero?
  979.         jz      dfkey1e                 ; z = zero, prompt for definition
  980.         jmp     dfkey1g                 ; process definition
  981.  
  982. dfkey1e:mov     ah,prstr
  983.         mov     dx,offset crlf
  984.         int     dos
  985.         mov     dx,offset dfaskdf       ; prompt for definition string
  986.         call    prompt                  ; Kermit prompt routine
  987.         mov     comand.cmcr,1           ; permit bare carriage returns
  988.     mov    comand.cmwhite,1    ; allow leading whitespace
  989. dfkey1f:mov     bx,offset tranbuf       ; get new definition
  990.         mov     word ptr [bx],0         ; insert terminator
  991.         mov     dx,offset dfhelp2       ; help for definition of key
  992.         mov     ah,cmline               ; read rest of line into tranbuf
  993.     call    comnd
  994.     jc    dfkey1x            ; exit now on ^C from user
  995.     cmp    comand.cmcr,0        ; prompting for definition?
  996.     je    dfkey1g            ; e = no, trim leading whitespace
  997.     mov    comand.cmcr,0        ; turn off allowance for bare c/r's
  998.     jmp    dfkey2            ; interactive, allow leading whitespace
  999. dfkey1x:ret                ; failure exit
  1000.  
  1001. dfkey1g:xchg    ah,al            ; put byte count in al
  1002.     xor    ah,ah            ; clear high byte
  1003.     mov    kbtemp,ax        ; and save count in kbtemp
  1004.     mov    ah,cmeol        ; get a confirm
  1005.     call    comnd
  1006.     jc    dfkey1x            ; none so declare parse error
  1007.     mov    cx,kbtemp        ; string length
  1008.     
  1009. dfkey2:                                 ; Examine translation
  1010.         mov     al,trans.escchr         ; current escape char (port dependent)
  1011.         cmp     al,byte ptr keycode     ; is this Kermit's escape char?
  1012.         jne     dfkey2a                 ; ne = no
  1013.         test    keycode,scan            ; see if scan code
  1014.         jnz     dfkey2a                 ; nz = scan, so not ascii esc char
  1015.     mov    dx,offset dfkoops    ; Oops! msg
  1016.     mov    ah,prstr        ; complain and don't redefine
  1017.     int    dos
  1018.     stc                ; failure
  1019.     ret
  1020.  
  1021. dfkey2a:push    di                      ; get a director code for this key
  1022.         push    cx
  1023.         mov     di,offset keylist       ; list of keycodes
  1024.         mov     cx,nkeys                ; number currently defined
  1025.         mov     ax,keycode              ; present keycode
  1026.         jcxz    dfkey2b                 ; cx = 0 means none defined yet
  1027.         cld
  1028.         push    ds
  1029.         pop     es
  1030.         repne   scasw                   ; is current keycode in the list?
  1031.         jne     dfkey2b                 ; ne = not in list
  1032.         sub     di,2                    ; correct for auto increment
  1033.         sub     di,offset keylist
  1034.         mov     listptr,di              ; list pointer for existing definition
  1035.         pop     cx
  1036.         pop     di
  1037.         jmp     dfkey3                  ; go process definition
  1038.  
  1039. dfkey2b:pop     cx                      ; key not currently defined so
  1040.         pop     di                      ;  make a new director entry for it
  1041.         mov     bx,nkeys                ; number of keys previously defined
  1042.         cmp     bx,maxkeys              ; enough space?
  1043.         jae     dfkey2c                 ; ae = no, complain
  1044.         shl     bx,1                    ; count words
  1045.         mov     listptr,bx              ; index into word list
  1046.         mov     ax,keycode              ; get key's code
  1047.         mov     keylist[bx],ax          ; store it in list of keycodes
  1048.         mov     dirlist[bx],0           ; clear the new director entry
  1049.         inc     nkeys                   ; new number of keys
  1050.         jmp     dfkey3                  ; go process definition
  1051.  
  1052. dfkey2c:mov     dx,offset keyfull       ; say key space is full already
  1053.         mov     ah,prstr
  1054.         int     dos
  1055.     stc                ; failure
  1056.     ret
  1057.  
  1058. ; listptr has element number in keylist or dirlist; keycode has key's code.
  1059.  
  1060. ; Parse new definition. First look for Kermit verbs as a line beginning
  1061. ; as \K or \{K. Otherwise, consider the line to be a string.
  1062. ; In any case, update the Director table for the new definition.
  1063.  
  1064. dfkey3: mov     brace,0                 ; assume not using braces
  1065.         mov     si,offset tranbuf       ; start of definition text
  1066.         cmp     byte ptr [si],'\'       ; starts with escape char?
  1067.         jne     dfkey5                  ; ne = no, so we have a string
  1068.         inc     si                      ; skip the backslash
  1069.         cmp     byte ptr [si],braceop   ; starts with \{?
  1070.         jne     dfkey3a                 ; ne = no
  1071.         inc     si                      ; skip the opening brace
  1072.         mov     brace,bracecl           ; expect closing brace
  1073. dfkey3a:cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  1074.         je      dfkey3b                 ; e = yes
  1075.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  1076.         jne     dfkey5                  ; ne = no, then it's a string
  1077. dfkey3b:inc     si                      ; yes, skip the K too
  1078.                                         ; Kermit action VERBS
  1079.         push    si                      ; save verb name start address
  1080. dfkey4:    cld
  1081.         lodsb                           ; scan til closing brace or w/s or end
  1082.         cmp     al,0                    ; premature end?
  1083.         je      dfkey4b                 ; e = yes, accept without brace
  1084.         cmp     al,brace                ; closing brace?
  1085.         je      dfkey4b                 ; e = yes
  1086.         cmp     al,spc                  ; white space or control char?
  1087.         ja      short dfkey4        ; a = no, so not at end yet
  1088. dfkey4b:mov     byte ptr[si-1],0        ; insert null terminator
  1089.         pop     si                      ; recover start address
  1090.         call    tstkeyw                 ; find keyword, kw # returned in kbtemp
  1091.         jc      dfkey4d                 ; c = no keyword found, complain
  1092.         call    remstr                  ; clear old string, if string
  1093.         mov     ax,kbtemp               ; save keyword number
  1094.         and     ax,not(verb+strng)      ; clear verb / string field
  1095.         or      ax,verb                 ; set verb ident
  1096.         mov     si,listptr
  1097.         mov     dirlist[si],ax          ; store info in Director table
  1098.         jmp     dfkey7                  ; show results and return success
  1099.  
  1100. dfkey4d:mov     dx,offset verbbad       ; say no such verb
  1101.         mov     ah,prstr
  1102.         int     dos
  1103.     stc                ; failure
  1104.     ret
  1105.  
  1106. ; Here we are left with the definition string; si points to its start, and
  1107. ; kbtemp holds its length (number of bytes). Null termination. If the string
  1108. ; begins with an opening brace it terminates on a matching closing brace
  1109. ; or the end of line, whichever occurs first. Trailing whitespace removed
  1110. ; before examining braces.
  1111. ; Null length strings mean define key as Self.
  1112.                                         ; STRING definitions
  1113. dfkey5: call    remstr                  ; first, clear old string, if any
  1114.         mov     si,offset tranbuf       ; si=source, di=dest, convert in-place
  1115.         mov     di,si
  1116.         call    cnvlin                  ; convert numbers, cx gets line length
  1117.         mov     si,offset tranbuf       ; provide address of new string
  1118.         cmp     cx,1                    ; just zero or one byte to do?
  1119.         jbe     dfkey6                  ; e = yes, do as a char
  1120.         call    insertst                ; insert new string, returns reg cx.
  1121.         jc      dfkey5h                 ; c = could not do insert
  1122.         mov     si,listptr              ; cx has type and string number
  1123.         mov     dirlist[si],cx          ; update Director table from insertst
  1124.         jmp     dfkey7                  ; show results and return success
  1125.  
  1126. dfkey5h:mov     dx,offset strbad        ; display complaint
  1127.         mov     ah,prstr
  1128.         int     dos
  1129.     stc                ; failure
  1130.     ret
  1131.  
  1132.                 ; define SINGLE CHAR replacement or CLEAR a key definition.
  1133.                 ; cx has char count 1 (normal) or 0 (to undefine the key).
  1134. dfkey6: jcxz    dfkey6c                 ; z = cx= 0, clear definition
  1135.         mov     al,byte ptr [si]        ; get first byte from definition
  1136.         xor     ah,ah                   ; set the type bits to Char
  1137.         mov     si,listptr
  1138.         mov     dirlist[si],ax          ; store type and key's new code
  1139.         jmp     dfkey7                  ; return success
  1140.  
  1141. dfkey6c:push    si                      ; clear a definition,
  1142.         push    di                      ; listptr points to current def
  1143.         mov     si,listptr              ; starting address to clear
  1144.         add     si,offset dirlist
  1145.         mov     di,si                   ; destination
  1146.         add     si,2                    ; source is next word
  1147.         mov     cx,nkeys                ; current number of keys defined
  1148.         add     cx,cx                   ; double for listptr being words
  1149.         sub     cx,listptr              ; cx = number of words to move
  1150.         shr     cx,1                    ; convert to actual number of moves
  1151.         jcxz    dfkey6d                 ; z = none, just remove last word
  1152.         push    es
  1153.         push    ds
  1154.         pop     es                      ; make es:di point to data segment
  1155.         cld
  1156.         push    cx                      ; save cx
  1157.         rep     movsw                   ; move down higher list items
  1158.         pop     cx
  1159.         mov     si,listptr              ; do keylist too, same way
  1160.         add     si,offset keylist
  1161.         mov     di,si
  1162.         add     si,2
  1163.         rep     movsw
  1164.         pop     es
  1165. dfkey6d:mov     si,nkeys                ; clear old highest list element
  1166.         shl     si,1                    ; address words
  1167.         mov     dirlist[si],0           ; null the element
  1168.         mov     keylist[si],0           ; null the element
  1169.         dec     nkeys                   ; say one less key defined now
  1170.         pop     di                      ; restore saved registers
  1171.         pop     si
  1172.  
  1173. dfkey7: mov     ah,msutake              ; Finish up. In a Take file?
  1174.         or      ah,taklev               ; or even directly
  1175.         cmp     ah,0
  1176.         je      dfkey7a                 ; e = no
  1177.         cmp     flags.takflg,0          ; echo Take commands?
  1178.         je      dfkey7b                 ; e = no
  1179. dfkey7a:mov     ah,prstr                ; display cr/lf
  1180.         mov     dx,offset crlf
  1181.         int     dos
  1182.         call    shkey0                  ; show new definition (in SHKEY)
  1183.         call    shkfre                  ; show free string space
  1184. dfkey7b:clc                ; return success
  1185.     ret
  1186. DFKEY   ENDP
  1187.  
  1188. ; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
  1189. ; command. Replaces obsolete procedure in msx---.
  1190. ; Prompts for a key and shows that key's (or all if ? entered) keycode,
  1191. ; definition, and the key definition free space remaining.
  1192.  
  1193. SHKEY   PROC    NEAR                    ; Show key's definition command
  1194.         mov     ah,cmeol                ; get a confirm
  1195.     call    comnd            ; ignore any additional text
  1196.         push    bx
  1197.         mov     dx,offset shkmsg1       ; ask for original key
  1198.         mov     ah,prstr
  1199.         int     dos
  1200. shky0:  call    getkey                  ; read keyboard, output to keycode
  1201.         jc      shky0                   ; wait for a key (c = nothing there)
  1202.         cmp     byte ptr keycode,'?'    ; query for all keys?
  1203.         jne     shky0a                  ; ne = no, not a query
  1204.         test    keycode,scan            ; is this a scan code, vs ascii query?
  1205.         jz      shky0c                  ; z = no Scan, so it is a query
  1206.  
  1207. shky0a: mov     ah,prstr                ; show single key. Setup display
  1208.         mov     dx,offset crlf
  1209.         int     dos
  1210.         call    shkey0                  ; show just one key
  1211. shky0b: call    shkfre                  ; show free string space
  1212.         jmp     shkeyx                  ; exit
  1213.  
  1214. shky0c: mov     cx,nkeys                ; Show all keys. nkeys = number defined
  1215.         jcxz    shky0b                  ; z = none to show
  1216.         mov     si,offset keylist       ; list of definitions
  1217.         push    si                      ; save pointer
  1218. shky1:  pop     si                      ; recover pointer
  1219.         cld
  1220.         lodsw                           ; get a keycode
  1221.         push    si                      ; save pointer
  1222.         push    cx                      ; save counter
  1223.         mov     keycode,ax              ; save new keycode
  1224.         mov     ah,prstr
  1225.         mov     dx,offset crlf
  1226.         int     dos
  1227.         call    shkey0                  ; show this keycode
  1228.  
  1229.         pop     cx                      ; pause between screens, recover cntr
  1230.         push    cx                      ; save it again
  1231.         dec     cx                      ; number yet to be shown
  1232.         jcxz    shky1b                  ; z = have now shown all of them
  1233.         mov     ax,nkeys                ; number of defined keys
  1234.         sub     ax,cx                   ; minus number yet to be displayed
  1235.         xor     dx,dx                   ; clear extended numerator
  1236.         div     twelve                  ; two lines per definition display
  1237.         or      dx,dx                   ; remainder zero (12 defs shown)?
  1238.         jnz     shky1b                  ; nz = no, not yet so keep going
  1239.         mov     ah,prstr
  1240.         mov     dx,offset shkmsg3       ; "push any key to continue" msg
  1241.         int     dos
  1242. shky1a: call    getkey                  ; get any key
  1243.         jc      shky1a                  ; c = nothing at keyboard yet, wait
  1244. shky1b: pop     cx                      ; resume loop
  1245.         loop    shky1
  1246.         pop     si                      ; clean stack
  1247.         call    shkfre                  ; show free string space
  1248.         jmp     shkeyx                  ; exit
  1249.  
  1250.                 ; show key worker routine, called from above
  1251.                                         ; SHKEY0 called by DFKEY just above
  1252. SHKEY0: test    keycode,scan            ; scan code?
  1253.         jz      shkey1                  ; z = no, regular ascii
  1254.  
  1255.                                         ; SCAN codes
  1256.         mov     dx,offset scanmsg       ; say Scan Code:
  1257.         mov     ah,prstr
  1258.         int     dos
  1259.         mov     ah,conout
  1260.         mov     dl,'\'                  ; add backslash before number
  1261.         int     dos
  1262.         mov     ax,keycode              ; get key's code again
  1263.         call    decout                  ; display 16 bit decimal keycode
  1264.         jmp     shkey2                  ; go get definition
  1265.  
  1266. shkey1: mov     dx,offset ascmsg        ; say ASCII CHAR
  1267.         mov     ah,prstr
  1268.         int     dos
  1269.         mov     dl,byte ptr keycode     ; get ascii code (al part of input)
  1270.         mov     ah,conout
  1271.         cmp     dl,spc                  ; control code?
  1272.         jae     shkey1a                 ; ae = no
  1273.         push    dx                      ; save char
  1274.         mov     dl,5eh                  ; show caret first
  1275.         int     dos
  1276.         pop     dx
  1277.         add     dl,'A'-1                ; ascii bias
  1278. shkey1a:cmp     dl,del                  ; DEL?
  1279.         jne     shkey1b                 ; ne = no
  1280.         mov     dl,'D'                  ; spell out DEL
  1281.         int     dos
  1282.         mov     dl,'E'
  1283.         int     dos
  1284.         mov     dl,'L'
  1285. shkey1b:int     dos
  1286.         mov     dl,spc                  ; add a couple of spaces
  1287.         int     dos
  1288.         int     dos
  1289.         mov     dl,'\'                  ; add backslash before number
  1290.         int     dos
  1291.         mov     ax,keycode              ; show 16 bit keycode in decimal
  1292.         call    decout                  ; and go get definiton
  1293.  
  1294.                                         ; Display defintion
  1295. shkey2: mov     dx,offset shkmsg2       ; intermediate part of reply
  1296.         mov     ah,prstr                ; " is defined as "
  1297.         int     dos
  1298.         push    di                      ; get a director code for this key
  1299.         push    cx
  1300.         mov     di,offset keylist       ; list of keycodes
  1301.         mov     cx,nkeys                ; number currently defined
  1302.         jcxz    shkey2a                 ; z = none
  1303.         mov     ax,keycode              ; present keycode
  1304.         push    ds
  1305.         pop     es                      ; use data segment for es:di
  1306.         cld
  1307.         repne   scasw                   ; is current keycode in the list?
  1308.         jne     shkey2a                 ; ne = not in list
  1309.         sub     di,2                    ; correct for auto increment
  1310.         sub     di,offset keylist
  1311.         mov     listptr,di              ; list pointer for existing definition
  1312.         pop     cx
  1313.         pop     di
  1314.         jmp     shkey3                  ; go process definition
  1315.  
  1316. shkey2a:pop     cx
  1317.         pop     di
  1318.         mov     dx,offset noxmsg        ; say Self (no translation)
  1319.         mov     ah,prstr
  1320.         int     dos
  1321.         ret                             ; return to main show key loop
  1322.  
  1323. shkey3:                                 ; translations, get kind of.
  1324.         mov     si,listptr
  1325.         test    dirlist[si],verb        ; defined as verb?
  1326.         jnz     shkey6                  ; nz = yes, go do that one
  1327.         test    dirlist[si],strng       ; defined as string?
  1328.         jz      shkey3a                 ; z = no
  1329.         jmp     shkey8                  ; yes, do string display
  1330. shkey3a:
  1331.         mov     dx,offset ascmsg        ; CHAR. say 'Ascii char:'
  1332.         mov     ah,prstr
  1333.         int     dos
  1334.         mov     ax,dirlist [si]         ; get type and char
  1335.         mov     dl,al                   ; put char here for display
  1336.         push    ax                      ; save here too
  1337.         mov     ah,conout
  1338.         cmp     dl,spc                  ; control code?
  1339.         jae     shkey4                  ; ae = no
  1340.         push    dx
  1341.         mov     dl,5eh                  ; show caret
  1342.         int     dos
  1343.         pop     dx
  1344.         add     dl,'A'-1                ; add ascii bias
  1345. shkey4: cmp     dl,del                  ; DEL?
  1346.         jne     shkey4a                 ; ne = no
  1347.         mov     dl,'D'                  ; spell out DEL
  1348.         int     dos
  1349.         mov     dl,'E'
  1350.         int     dos
  1351.         mov     dl,'L'
  1352. shkey4a:int     dos
  1353.         mov     dl,spc                  ; add a couple of spaces
  1354.         mov     ah,conout
  1355.         int     dos
  1356.         int     dos
  1357.         mov     dl,'\'                  ; add backslash before number
  1358.         int     dos
  1359.         pop     ax                      ; recover char
  1360.         xor     ah,ah                   ; clear high byte
  1361.         call    decout                  ; show decimal value
  1362.         ret                             ; return to main show key loop
  1363.  
  1364. shkey6: mov     ah,prstr                ; VERB
  1365.         mov     dx,offset verbmsg       ; say 'verb'
  1366.         int     dos
  1367.         mov     si,listptr              ; get verb index from director
  1368.         mov     dx,dirlist[si]
  1369.         and     dx,not(verb+strng)      ; remove type bits, leaves verb number
  1370.         mov     bx,offset kverbs        ; table of verbs & actions
  1371.         mov     al,byte ptr [bx]        ; number of keywords
  1372.         xor     ah,ah
  1373.         dec     ax
  1374.         mov     kwcnt,ax                ; save number of last one here
  1375.         cmp     dx,ax                   ; asking for more than we have?
  1376.         ja      shkeyx                  ; a = yes, exit bad
  1377.         inc     bx                      ; point to first slot
  1378.         mov     cx,0                    ; current slot number
  1379. shkey6b:cmp     cx,dx                   ; this slot?
  1380.         je      shkey6c                 ; e = yes, print the text part
  1381.         ja      shkeyx                  ; a = beyond, exit bad
  1382.         mov     al,byte ptr [bx]        ; get cnt (keyword length)
  1383.         xor     ah,ah
  1384.         add     ax,4                    ; skip over '$' and two byte value
  1385.         add     bx,ax                   ; bx = start of next keyword slot
  1386.         inc     cx                      ; current keyword number
  1387.         jmp     short shkey6b           ; try another
  1388. shkey6c:inc     bx                      ; look at text field
  1389.         mov     dx,bx                   ; offset for printing
  1390.         mov     ah,prstr
  1391.         int     dos
  1392.         mov     ah,conout
  1393.         mov     dl,spc                  ; add a couple of spaces
  1394.         int     dos
  1395.         int     dos
  1396.         mov     dl,'\'                  ; show verb name as \Kverb
  1397.         int     dos
  1398.         mov     dl,'K'
  1399.         int     dos
  1400.         mov     ah,prstr
  1401.         mov     dx,bx                   ; show name part again
  1402.         int     dos
  1403.         ret                             ; return to main show key loop
  1404.  
  1405. shkey8: mov     ah,prstr                ; STRING
  1406.         mov     dx,offset strngmsg      ; say String:
  1407.         int     dos
  1408.         mov     si,listptr              ; get index from director
  1409.         mov     bx,dirlist[si]
  1410.         and     bx,not(verb+strng)      ; remove type bits
  1411.         shl     bx,1                    ; index words
  1412.         mov     si,sptable[bx]          ; table of string offsets
  1413.         mov     cl,byte ptr [si]        ; get string length byte
  1414.         xor     ch,ch
  1415.         inc     si                      ; point to string text
  1416.         mov     ah,conout
  1417. shkey8a:cld
  1418.         lodsb                           ; get a byte
  1419.         cmp     al,spc                  ; control code?
  1420.         jae     shkey8b                 ; ae = no
  1421.         push    ax
  1422.         mov     dl,5eh                  ; show caret first
  1423.         int     dos
  1424.         pop     ax
  1425.         add     al,40h                  ; convert to printable for display
  1426. shkey8b:mov     dl,al
  1427.         int     dos                     ; display it
  1428.         loop    shkey8a                 ; do another
  1429.         ret                             ; return to main show key loop
  1430.  
  1431. shkeyx: pop     bx                      ; restore reg
  1432.     clc                ; return success
  1433.     ret
  1434. SHKEY   ENDP
  1435.  
  1436. ;;;     keyboard translator local support procedures, system independent
  1437.  
  1438. ; Tstkeyw checks text word pointed to by si against table of keywords (pointed
  1439. ; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
  1440. ; Returns in kbtemp the number of the keyword and carry clear, or if failure
  1441. ; returns kbtemp zero and carry set.
  1442. ; Keyword structure is:         db      cnt     (length of string 'word')
  1443. ;                               db      'word'  (keyword string)
  1444. ;                               db      '$'     (printing terminator)
  1445. ;                               dw      value   (value returned in bx)
  1446. ; Make these with macro mkeyw such as   mkeyw 'test',15   with the list of
  1447. ; such keywords headed by a byte giving the number of keywords in the list.
  1448. tstkeyw proc    near
  1449.         push    ax
  1450.         push    cx
  1451.         push    si
  1452.         mov     verblen,0               ; verblen will hold verb length
  1453.         push    si                      ; save user's verb pointer
  1454. tstkw1: cld
  1455.         lodsb                           ; get a verb character
  1456.         cmp     al,spc                  ; verbs are all non-spaces and above
  1457.         jbe     tstkw2                  ; be = done (space or control char)
  1458.         inc     verblen                 ; count verb length
  1459.         jmp     short tstkw1            ; printable char, look for more
  1460. tstkw2: pop     si                      ; pointer to verb
  1461.         mov     bx,offset kverbs        ; table of Kermit verb keywords
  1462.         mov     al,byte ptr [bx]        ; number of keywords
  1463.         xor     ah,ah
  1464.         mov     kwcnt,ax                ; save number of keywords here
  1465.         inc     bx                      ; point bx to first slot
  1466.         mov     kbtemp,0                ; remember which keyword
  1467.  
  1468. tstkw3:                                 ; match table keyword and text word
  1469.         mov     cx,verblen              ; length of user's verb
  1470.         cmp     byte ptr [bx],cl        ; compare length vs table keyword
  1471.         jne     tstkw4                  ; ne = not equal lengths, try another
  1472.         push    si                      ; lengths match, how about spelling?
  1473.         push    bx
  1474.         inc     bx                      ; point at start of keyword
  1475. tstkw3a:mov     ah,byte ptr [bx]        ; keyword char
  1476.         mov     al,byte ptr [si]        ; text char
  1477.         cmp     ah,'A'
  1478.         jb      tstkw3b                 ; b = control chars
  1479.         cmp     ah,'Z'
  1480.         ja      tstkw3b                 ; a = not upper case alpha
  1481.         add     ah,'a'-'A'              ; convert upper case to lower case
  1482. tstkw3b:cmp     al,'A'
  1483.         jb      tstkw3c
  1484.         cmp     al,'Z'
  1485.         ja      tstkw3c
  1486.         add     al,'a'-'A'              ; convert upper case to lower case
  1487. tstkw3c:cmp     al,ah                   ; test characters
  1488.         jne     tstkw3d                 ; ne = no match
  1489.         inc     si                      ; move to next char
  1490.         inc     bx
  1491.         loop    tstkw3a                 ; loop through entire length
  1492. tstkw3d:pop     bx
  1493.         pop     si
  1494.         jcxz    tstkw5                  ; z: cx = 0, exit with match;
  1495.                                         ;  else select next keyword
  1496. tstkw4: inc     kbtemp                  ; number of keyword to test next
  1497.         mov     cx,kbtemp
  1498.         cmp     cx,kwcnt                ; all done? Recall kbtemp starts at 0
  1499.         jae     tstkwx                  ;ae = exhausted search, unsuccessfully
  1500.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  1501.         xor     ah,ah
  1502.         add     ax,4                    ; skip over '$' and two byte value
  1503.         add     bx,ax                   ; bx = start of next keyword slot
  1504.         jmp     tstkw3                  ; do another comparison
  1505.  
  1506. tstkw5:                                 ; get action pointer
  1507.         mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
  1508.         xor     ah,ah
  1509.         add     ax,2                    ; skip over '$'
  1510.         add     bx,ax                   ; now bx points to dispatch value
  1511.         mov     bx,[bx]                 ; bx holds dispatch value
  1512.         clc                             ; carry clear for success
  1513.         jmp     short tstkwxx           ; exit
  1514.         ret
  1515. tstkwx: xor     bx,bx                   ; exit when no match
  1516.         mov     kbtemp,bx               ; make verb number be zero too
  1517.         stc                             ; carry set for failure
  1518. tstkwxx:pop     si
  1519.         pop     cx
  1520.         pop     ax
  1521.         ret
  1522. tstkeyw endp
  1523.  
  1524. ; Insert asciiz string pointed to by si into string buffer stbuf.
  1525. ; Reg cx has string length upon entry.
  1526. ; Success: returns offset of first free byte (strmax) in string buffer stbuf,
  1527. ; cx = type and Index of new string, and carry clear.
  1528. ; Failure = carry set.
  1529. insertst proc   near
  1530.         push    bx
  1531.         push    dx
  1532.         push    si
  1533.         push    di
  1534.         push    kbtemp          ; save this variable too
  1535.         mov     dx,cx           ; save length of incoming string in dx
  1536.         mov     bx,offset sptable ; table of string offsets
  1537.         mov     kbtemp,0        ; slot number
  1538.         mov     cx,maxstng      ; number of entries, find an empty slot
  1539. insert1:cmp     word ptr[bx],0  ; slot empty?
  1540.         je      insert2         ; e = yes
  1541.         inc     kbtemp          ; remember slot number
  1542.         add     bx,2            ; look at next slot
  1543.         loop    insert1         ; keep looking
  1544.         jmp     short insert4   ; get here if no empty slots
  1545. insert2:                        ; see if stbuf has sufficient space
  1546.         mov     cx,dx           ; length of new string to cx
  1547.         mov     di,strmax       ; offset of first free byte in stbuf
  1548.         add     di,cx           ; di = address where this string would end
  1549.         cmp     di,offset stbuf+stbuflen ; beyond end of buffer?
  1550.         jae     insert4         ; ae = yes, not enough room
  1551.         mov     di,strmax       ; point to first free slot in stbuf
  1552.         mov     [bx],di         ; fill slot with address offset of buffer
  1553.         push    es
  1554.         push    ds
  1555.         pop     es              ; point es:di to data segment
  1556.         cld
  1557.         mov     byte ptr [di],cl ; length of text for new string
  1558.         inc     di              ; move to next storage slot
  1559.         rep     movsb           ; copy string text
  1560.         pop     es
  1561.         mov     strmax,di       ; offset of next free byte
  1562.         mov     cx,kbtemp       ; return new slot number with Director Index
  1563.         and     cx,not(strng+verb) ; clear type bits
  1564.         or      cx,strng        ; say type is multi-char string
  1565.         clc                     ; say success
  1566.         jmp     short insertx   ; exit
  1567. insert4:stc                     ; say no-can-do
  1568. insertx:pop     kbtemp
  1569.         pop     di
  1570.         pop     si
  1571.         pop     dx
  1572.         pop     bx
  1573.         ret
  1574. insertst endp
  1575.  
  1576. ; Remove (delete) string. Enter with listptr preset for director entry.
  1577. ; Acts only on existing multi-char strings; recovers freed space.
  1578. ; All registers preserved.
  1579. remstr  proc    near
  1580.         push    si
  1581.         mov     si,listptr              ; list pointer
  1582.         test    dirlist[si],strng       ; multi-char string?
  1583.         pop     si
  1584.         jnz     remst1                  ; nz = a multi-char string
  1585.         ret                             ; else do nothing
  1586. remst1: push    ax
  1587.         push    bx
  1588.         push    cx
  1589.         push    dx
  1590.         push    si
  1591.         mov     si,listptr
  1592.         mov     ax,dirlist[si]          ; Director table entry
  1593.         and     ax,not(strng+verb) ; clear type bits, leave string's pointer
  1594.         mov     dirlist[si],0           ; clear Director table entry
  1595.         shl     ax,1                    ; index words not bytes
  1596.         mov     si,offset sptable       ; list of string offsets in stbuf
  1597.         add     si,ax                   ; plus index = current slot
  1598.         mov     bx,[si]                 ; get offset of string to be deleted
  1599.         mov     dx,bx                   ; save in dx for later
  1600.         mov     cl,byte ptr [bx]        ; get length byte
  1601.         xor     ch,ch                   ; get length of subject string
  1602.         inc     cx                      ; length byte too, cx has whole length
  1603.         sub     strmax,cx       ; count space to be freed (adj end-of-buf ptr)
  1604.         mov     word ptr [si],0 ; clear sptable of subject string address
  1605.         push    cx                      ; save length of purged string
  1606.         push    di                      ; save di
  1607.         push    si
  1608.         push    es                      ; save es
  1609.         push    ds
  1610.         pop     es              ; setup es:di to be ds:offset of string
  1611.         mov     di,dx           ; destination = start address of purged string
  1612.         mov     si,dx           ; source = start address of purged string
  1613.         add     si,cx           ;  plus string length of purged string.
  1614.         mov     cx,offset stbuf+stbuflen ; 1 + address of buffer end
  1615.         sub     cx,si                   ; 1 + number of bytes to move
  1616.         dec     cx                      ; number of bytes to move
  1617.         jcxz    remst2                  ; z = none
  1618.         cld                             ; direction is forward
  1619.         rep     movsb                   ; move down preserved strings
  1620. remst2: pop     es                      ; restore regs
  1621.         pop     di
  1622.         pop     si
  1623.         pop     ax              ; recover length of purged string (was in cx)
  1624.         mov     bx,offset sptable       ; string pointer table
  1625.         mov     cx,maxstng              ; max mumber of entries
  1626. remst4: cmp     [bx],dx         ; does this entry occur before purged string?
  1627.         jbe     remst5          ; be = before or equal, so leave it alone
  1628.         sub     [bx],ax         ; recompute address (remove old string space)
  1629. remst5: add     bx,2                    ; look at next list entry
  1630.         loop    remst4                  ; do all entries in sptable
  1631.         pop     si
  1632.         pop     dx
  1633.         pop     cx
  1634.         pop     bx
  1635.         pop     ax
  1636.         ret
  1637. remstr  endp
  1638.  
  1639. shkfre  proc    near                    ; show free key & string defs & space
  1640.         push    ax                      ; preserves all registers.
  1641.         push    bx
  1642.         push    cx
  1643.         push    dx
  1644.         push    kbtemp
  1645.         mov     dx,offset fremsg
  1646.         mov     ah,prstr
  1647.         int     dos
  1648.         mov     ax,maxkeys              ; max number of key defs
  1649.         sub     ax,nkeys                ; number currently used
  1650.         call    decout                  ; show the value
  1651.         mov     ah,prstr
  1652.         mov     dx,offset kyfrdef       ; give key defs msg
  1653.         int     dos
  1654.         mov     bx,offset sptable       ; table of string pointers
  1655.         mov     cx,maxstng              ; number of pointers
  1656.         mov     kbtemp,0                ; number free
  1657. shkfr1: cmp     word ptr [bx],0         ; slot empty?
  1658.         jne     shkfr2                  ; ne = no
  1659.         inc     kbtemp                  ; count free defs
  1660. shkfr2: add     bx,2                    ; look at next slot
  1661.         loop    shkfr1                  ; do all of them
  1662.         mov     ax,kbtemp               ; number of free defs
  1663.         call    decout                  ; display
  1664.         mov     dx,offset stfrdef       ; say free string defs
  1665.         mov     ah,prstr
  1666.         int     dos
  1667.         mov     ax,offset stbuf+stbuflen ; 1 + last byte in stbuf
  1668.         sub     ax,strmax               ; offset of last free byte in stbuf
  1669.         call    decout
  1670.         mov     dx,offset stfrspc       ; give free space part of msg
  1671.         mov     ah,prstr
  1672.         int     dos
  1673.         pop     kbtemp
  1674.         pop     dx
  1675.         pop     cx
  1676.         pop     bx
  1677.         pop     ax
  1678.         ret
  1679. shkfre  endp
  1680.  
  1681. ; Initialize the keyboard tables at Kermit startup time. Optional procedure.
  1682. ; Requires kbdinlst to be configured with mkeyw macro in the form
  1683. ;       mkeyw   'definition',keytype*256+keycode
  1684. ; keytype is 0 for scan codes and non-zero for ascii.
  1685. ; Returns normally.
  1686. kbdinit proc    near                    ; read keyword kbdinlst and setup
  1687.         push    ds                      ;  initial keyboard assignments.
  1688.         pop     es                      ; set es:di to data segment
  1689.         mov     taklev,1                ; pretend that we are in Take file
  1690.         mov     si,offset kbdinlst      ; start of list of definitions
  1691. kbdini1:mov     cl,byte ptr [si]        ; cnt field (keyword length of macro)
  1692.         xor     ch,ch
  1693.         jcxz    kbdinix                 ; z = null cnt field = end of list
  1694.         inc     si                      ; look at text field
  1695.         mov     di,offset tranbuf       ; where defkey expects text
  1696.         cld
  1697.         rep     movsb                   ; copy cx chars to tranbuf
  1698.         mov     byte ptr [di],0         ; insert null terminator
  1699.         inc     si                      ; skip '$' field
  1700.         mov     ax,word ptr [si]        ; get value field
  1701.         mov     keycode,ax              ; set key ident value
  1702.         push    si
  1703.         call    dfkey2                  ; put dfkey to work
  1704.         pop     si
  1705.         add     si,2                    ; point to next entry
  1706.         jmp     kbdini1                 ; keep working
  1707. kbdinix:dec    taklev            ; reset Take file level
  1708.         ret
  1709. kbdinit endp
  1710. ;;;     End of System Independent Procedures
  1711.  
  1712. ;;;     Begin System Dependent Procedures
  1713.  
  1714. ans_keystr    proc    near
  1715. ; returns key definition strings.
  1716. ; inputs:
  1717. ;   ax scan code for the key
  1718. ; outputs:
  1719. ;   cx number of strings (may be zero)
  1720. ;   bx address of the string buffer
  1721. ;
  1722.     xor    cx,cx        ; clear counter
  1723.     cmp    nkeys,0
  1724.     jg    ans_keystr1
  1725.     jmp    ans_keystrex
  1726. ans_keystr1:
  1727.     push    di                      ; search keylist for this keycode
  1728.     push    cx                      ; save some registers
  1729.     push    es
  1730.     mov     di,offset keylist       ; list of defined keycode words
  1731.     mov     cx,nkeys                ; number of words to examine
  1732.     push    ds
  1733.     pop     es                      ; make es:di point to data segment
  1734.     cld
  1735.     repne   scasw                   ; find keycode in list
  1736.     pop     es                      ; restore regs
  1737.     pop     cx
  1738.     je    ans_keystr2        ; e = found, work with present di
  1739.     pop     di            ; restore original di
  1740.     jmp    ans_keystrex
  1741. ans_keystr2:
  1742.     sub    di,2            ; correct for auto increment
  1743.     sub    di,offset keylist    ; subtract start of list ==> listptr
  1744.     mov    bx,offset dirlist    ; get the director address
  1745.     add    bx,di
  1746.     pop     di                      ; restore original di
  1747.                                         ; dispatch on Director code
  1748.     mov    ax,[bx]
  1749.         test    ax,verb                 ; verb only?
  1750.         jnz     ans_keystrex        ; nz = yes
  1751.     test    ax,strng        ; multi-char string only?
  1752.         jnz    ans_keystr3        ; nz = yes, else single char & no xlat.
  1753.      mov    cx,1            ; do single CHAR output (char in al)
  1754.      inc    bx
  1755.      jmp    ans_keystrex
  1756. ;
  1757. ans_keystr3:
  1758.     and    ax,not(verb+strng)    ; STRING (ax=index, remove type bits)
  1759.     shl    ax,1            ; convert to word index
  1760.     push    si            ; save working reg
  1761.     mov    si,ax            ; word subscript in table
  1762.     mov    bx,sptable[si]        ; memory offset of selected string
  1763.     pop    si
  1764.         cmp     bx,0            ; is there a string pointer present?
  1765.     je    ans_keystrex        ; e = no, skip operation
  1766.     mov    cl,[bx]            ; get string length byte
  1767.     xor    ch,ch            ; to cx
  1768.     inc    bx            ; adjust pointer
  1769. ;
  1770. ans_keystrex:
  1771.         ret
  1772. ans_keystr    endp
  1773.  
  1774. ; Read keyboard. System dependent.
  1775. ; Return carry set if nothing at keyboard.
  1776. ; If char present return carry clear with key's code in Keycode.
  1777. ; If key is ascii put that in the low byte of Keycode and clear bit Scan in
  1778. ; the high byte; otherwise, put the scan code in the lower byte and set bit
  1779. ; Scan in the high byte.
  1780. ; Bit Scan is set if key is not an ascii code.
  1781. ; Modifies register ax.
  1782. getkey  proc    near
  1783.     cmp    intrkey,0        ; Interrupt key pressed ?
  1784.     jne    getkey01        ; ne = Yes.
  1785.     jmp    getkey00        ; go to normal process
  1786. getkey01:
  1787.     push    bx
  1788.     mov    ax,intrkey
  1789.     dec    ax            ; index starts from 1
  1790.     shl    ax,1            ; item size in the table is 2 bytes
  1791.     mov    bx,offset intkey_tab    ; set table
  1792.     add    bx,ax            ; add index
  1793.     mov    ax,[bx]            ; get keycode
  1794.     mov    intrkey,0        ; clear index
  1795.     pop    bx
  1796.     jmp    getkey1
  1797. getkey00:
  1798.         mov     keycode,0
  1799.     cmp    keyin_dos,0        ; Keyinput using BIOS ?
  1800.     je    getkey0            ; e = yes, BIOS key input
  1801.     cmp    keyin_dos,1        ; Keyinput using CON ?
  1802.     jne    getkey02        ; ne = no
  1803.     jmp    getkey_con
  1804. getkey02:
  1805.     jmp    getkey_dos
  1806. ;
  1807. ; Keyinput using BIOS
  1808. ;
  1809. getkey0:
  1810.         mov     ah,sense_key
  1811.         int    bios
  1812.     cmp    bh,0
  1813.         jne     getky1                  ; ne = char available
  1814.     stc                ; carry set = nothing available
  1815.         jmp    getkyx            ; exit on no char available
  1816. getky1:
  1817.     mov    ah,read_key
  1818.     int    bios
  1819.     cmp    al,'^'            ; check SHIFT+'^'
  1820.     jne    getky1_2
  1821.     mov    ah,sense_shift
  1822.     int    bios
  1823.     test    al,1
  1824.     jz    getky1_1
  1825.     mov    ax,0C60h        ; Back quote
  1826.     jmp    getkey1
  1827. getky1_1:
  1828.     mov    ax,0C5Eh        ; '^'
  1829.     jmp    getkey1
  1830. getky1_2:
  1831.     cmp    ah,34h
  1832.     jb    getkey1
  1833.     cmp    ah,3Fh
  1834.     ja    getkey1
  1835.     push    dx
  1836.     mov    dx,ax            ; save code
  1837.     mov    ah,sense_shift        ; sense shift key
  1838.     int    bios
  1839.     test    al,10h            ; CTRL pressed ?
  1840.     jz    getky1_3        ; z = no
  1841.     add    dx,08000h
  1842.     jmp    getky1_4
  1843. getky1_3:
  1844.     test    al,1            ; SHIFT pressed ?
  1845.     jz    getky1_4        ; z = no
  1846.     add    dx,07000h
  1847. getky1_4:
  1848.     xchg    ax,dx
  1849.     pop    dx
  1850. getkey1:
  1851.         push    di                      ; check key (ax) for aliases
  1852.         push    cx
  1853.         push    es
  1854.         mov     di,offset aliaskey      ; list of aliased keys
  1855.         mov     cx,aliaslen             ; number of entries
  1856.         jcxz    getky2                  ; z = no entries
  1857.         push    ds
  1858.         pop     es                      ; make es:di point to data segment
  1859.         cld
  1860.         repne   scasw                   ; look for a match
  1861.         jne     getky2                  ; ne = not there
  1862.         mov     al,0                    ; force use of scan code (in ah)
  1863. getky2: pop     es
  1864.         pop     cx
  1865.         pop     di
  1866.         or      al,al                   ; scan code being returned?
  1867.         jnz     getky3                  ; nz = no
  1868.         cmp    ax,1A00h        ; CTRL-@ key ?
  1869.         je    getky3
  1870.         xchg    ah,al                   ; put scan code in ident area
  1871.         or      keycode,scan            ; set scan flag (vs ascii)
  1872. getky3: mov     byte ptr keycode,al     ; return key's code (usually ascii)
  1873.         clc                             ; carry clear = got a char
  1874. getkyx: ret
  1875. ;
  1876. ; Keyinput using MS-DOS console I/O + sense shift key
  1877. ;
  1878. getkey_con:
  1879.     push    dx
  1880.     mov    ah,6            ; direct console I/O
  1881.     mov    dl,0FFh            ; read
  1882.     int    dos
  1883.     jnz    getkey_con6
  1884.     jmp    getkey_con0
  1885. getkey_con6:
  1886.     cmp    al,0FFh            ; special key ?
  1887.     jne    getkey_con61        ; ne = no
  1888.     jmp    getkey_conS
  1889. getkey_con61:
  1890.     mov    dx,ax
  1891.     mov    ah,sense_shift        ; sense shift key
  1892.     int    bios
  1893.     xchg    ax,dx            ; now ax=code, dx=shift_key
  1894.     cmp    al,3Dh            ; is it '=' key ?
  1895.     jne    getkey_con4
  1896.     jmp    getkey_conK        ; goto keypad-key check
  1897. getkey_con4:
  1898.     cmp    al,2Ah
  1899.     jb    getkey_con3
  1900.     cmp    al,39h
  1901.     ja    getkey_con3
  1902.     jmp    getkey_conK        ; goto keypad-key check
  1903. getkey_con3:                ; Normal key
  1904.     mov    ah,0
  1905.     cmp    al,'^'
  1906.     jne    getkey_con5
  1907.     test    dl,1            ; SHIFT pressed ?
  1908.     jz    getkey_con2        ; z = no
  1909.     mov    al,60h            ; backquote
  1910.     jmp    getkey_con2
  1911. getkey_con5:
  1912.     cmp    al,20h
  1913.     ja    getkey_con2
  1914.     cmp    al,8            ; BS ?
  1915.     jne    getkey_con51        ; ne = No.
  1916.     mov    ah,22h            ; assume CTRL + H
  1917.     test    dl,10h            ; test CTRL key
  1918.     jnz    getkey_con2        ; nz = Pressed.
  1919.     mov    ah,0Eh            ; BS key
  1920.     jmp    getkey_con2
  1921. getkey_con51:
  1922.     cmp    al,9            ; TAB ?
  1923.     jne    getkey_con52        ; ne = No.
  1924.     mov    ah,17h            ; assume CTRL + I
  1925.     test    dl,10h            ; test CTRL key
  1926.     jnz    getkey_con2        ; nz = Pressed.
  1927.     mov    ah,0Fh            ; TAB key
  1928.     jmp    getkey_con2
  1929. getkey_con52:
  1930.     cmp    al,1Bh            ; ESC ?
  1931.     jne    getkey_con53        ; ne = No.
  1932.     mov    ah,1Bh            ; assume CTRL + [
  1933.     test    dl,10h            ; test CTRL key
  1934.     jnz    getkey_con2        ; nz = Pressed.
  1935.     mov    ah,0            ; ESC key
  1936.     jmp    getkey_con2
  1937. getkey_con53:
  1938.     cmp    al,0            ; NUL ?
  1939.     jne    getkey_con54        ; ne = No.
  1940.     mov    ah,1Ah            ; CTRL + @
  1941.     jmp    getkey_con2
  1942. getkey_con54:
  1943.     cmp    al,20h            ; SPACE ?
  1944.     jne    getkey_con55        ; ne = No.
  1945.     mov    ah,34h            ; set scan code
  1946.     test    dl,10h            ; test CTRL key
  1947.     jz    getkey_con2        ; z = Not Pressed.
  1948.     mov    ax,0B420h        ; CTRL-SPACE
  1949. getkey_con55:
  1950. getkey_con2:
  1951.     pop    dx
  1952.     jmp    getkey1
  1953. getkey_con0:
  1954.     pop    dx
  1955.     stc
  1956.     ret
  1957. ;
  1958. getkey_conS:
  1959.     mov    ah,6
  1960.     mov    dl,0FFh
  1961.     int    dos
  1962.     jnz    getkey_conS1
  1963.     jmp    getkey_con0
  1964. getkey_conS1:
  1965.     mov    ah,al
  1966.     xor    al,al
  1967.     cmp    ah,34h
  1968.     jb    getkey_conS4
  1969.     cmp    ah,3Fh
  1970.     ja    getkey_conS4
  1971.     push    dx
  1972.     mov    dx,ax            ; save code
  1973.     mov    ah,sense_shift        ; sense shift key
  1974.     int    bios
  1975.     test    al,10h            ; CTRL pressed ?
  1976.     jz    getkey_conS2        ; z = no
  1977.     add    dx,08000h
  1978.     jmp    getkey_conS3
  1979. getkey_conS2:
  1980.     test    al,1            ; SHIFT pressed ?
  1981.     jz    getkey_conS3        ; z = no
  1982.     add    dx,07000h
  1983. getkey_conS3:
  1984.     xchg    ax,dx
  1985.     pop    dx
  1986. getkey_conS4:
  1987.     jmp    getkey_con2
  1988. ;
  1989. getkey_conK:
  1990.     mov    bx,offset keypadgrp
  1991.     xor    ah,ah
  1992.     mov    dx,ax
  1993.     sub    ax,2Ah
  1994.     shl    ax,1
  1995.     add    bx,ax
  1996.     mov    ax,[bx]
  1997.     mov    bx,ax
  1998.     xor    bl,bl
  1999.     mov    ah,04h
  2000.     int    BIOS
  2001.     test    ax,bx
  2002.     jnz    getkey_conK1
  2003.     mov    ax,dx
  2004.     jmp    getkey_con2
  2005. getkey_conK1:
  2006.     mov    ax,dx
  2007.     mov    bx,offset keypadnum
  2008.     sub    ax,2Ah
  2009.     shl    ax,1
  2010.     add    bx,ax
  2011.     mov    ax,[bx]
  2012.     jmp    getkey_con2
  2013.  
  2014. getkey_dos:
  2015.     push    dx
  2016.     mov    ah,6            ; direct console I/O
  2017.     mov    dl,0FFh            ; read
  2018.     int    dos
  2019.     jnz    getkey_dos6
  2020.     jmp    getkey_dos0
  2021. getkey_dos6:
  2022.     cmp    al,0FFh            ; special key ?
  2023.     je    getkey_dos1        ; e = yes
  2024.     jmp    getkey_dos2
  2025. getkey_dos1:
  2026.     mov    ah,6
  2027.     mov    dl,0FFh
  2028.     int    dos
  2029.     jz    getkey_dos0
  2030.     mov    ah,al
  2031.     xor    al,al
  2032. getkey_dos2:
  2033.     pop    dx
  2034.     jmp    getkey1
  2035. getkey_dos0:
  2036.     pop    dx
  2037.     stc
  2038.     ret
  2039.  
  2040. getkey  endp
  2041.  
  2042.  
  2043. postkey proc    near                    ; do sys dep action after reading
  2044.     test    vt100_flags,KEYCLICK_BIT
  2045.     je    postkey_ex
  2046.     push    ax
  2047.     push    cx
  2048. ;
  2049.     mov    al,06h
  2050.     out    37h,al            ; bell on
  2051.     mov    cx,1000h
  2052. postkey1:
  2053.     loop    postkey1
  2054. ;
  2055.     mov    al,07h
  2056.     out    37h,al            ; bell off
  2057. ;
  2058.     pop    cx
  2059.     pop    ax
  2060. postkey_ex:
  2061.         ret                             ; key during active translation
  2062. postkey endp
  2063.  
  2064. ; Interrupt routine for STOP and COPY keys
  2065.  
  2066. keyint_entry    proc    far
  2067. stop_int:
  2068.     push    ax
  2069.     push    ds
  2070. ;
  2071.     mov    ax,data
  2072.     mov    ds,ax
  2073.     cmp    intrkey,0
  2074.     jne    keyint_entry3
  2075.     mov    intrkey,1
  2076.     jmp    keyint_entry1
  2077. ;
  2078. copy_int:
  2079.     push    ax
  2080.     push    ds
  2081. ;
  2082.     mov    ax,data
  2083.     mov    ds,ax
  2084.     cmp    intrkey,0
  2085.     jne    keyint_entry3
  2086.     mov    intrkey,2
  2087. ;
  2088. keyint_entry1:
  2089. ;
  2090.     mov    ah,sense_shift
  2091.     int    bios
  2092.     test    al,10h            ; CTRL?
  2093.     jz    keyint_entry2
  2094.     add    intrkey,4
  2095.     jmp    keyint_entry3
  2096. keyint_entry2:
  2097.     test    al,1            ; SHIFT?
  2098.     jz    keyint_entry3
  2099.     add    intrkey,2
  2100. keyint_entry3:
  2101. ;
  2102.     pop    ds
  2103.     pop    ax
  2104.     iret
  2105. keyint_entry    endp
  2106.  
  2107. ; Keyboard local initialization routine
  2108.  
  2109. kbdlini    proc    near
  2110.     pushf
  2111.     cli                ; disable interrupt
  2112. ;
  2113.     push    ax
  2114.     push    bx
  2115.     push    dx
  2116.     push    es
  2117. ;
  2118.     mov    intrkey,0
  2119. ;
  2120.     mov    ah,35h            ; read interrupt vector
  2121.     mov    al,INTNUM_COPY        ; for COPY key interrupt
  2122.     int    DOS            ; system call
  2123.     mov    old_copy_ofs,bx        ; save vector
  2124.     mov    old_copy_sgm,es
  2125. ;
  2126.     mov    ah,35h            ; read interrupt vector
  2127.     mov    al,INTNUM_STOP        ; for STOP key interrupt
  2128.     int    DOS            ; system call
  2129.     mov    old_stop_ofs,bx        ; save vector
  2130.     mov    old_stop_sgm,es
  2131. ;
  2132.     mov    dx,offset copy_int
  2133.     mov    ax,cs
  2134.     push    ds
  2135.     mov    ds,ax
  2136.     mov    ah,25h
  2137.     mov    al,INTNUM_COPY
  2138.     int    DOS
  2139.     pop    ds
  2140. ;
  2141.     mov    dx,offset stop_int
  2142.     mov    ax,cs
  2143.     push    ds
  2144.     mov    ds,ax
  2145.     mov    ah,25h
  2146.     mov    al,INTNUM_STOP
  2147.     int    DOS
  2148.     pop    ds
  2149. ;
  2150.     pop    es
  2151.     pop    dx
  2152.     pop    bx
  2153.     pop    ax
  2154. ;
  2155.     popf
  2156.     ret
  2157. kbdlini    endp
  2158.  
  2159. ; keyboard local end routine
  2160.  
  2161. kbdlend    proc    near
  2162.     pushf
  2163.     cli                ; disable interrupt
  2164. ;
  2165.     push    ax
  2166.     push    dx
  2167. ;
  2168.     mov    dx,old_stop_ofs
  2169.     mov    ax,old_stop_sgm
  2170.     push    ds
  2171.     mov    ds,ax
  2172.     mov    ah,25h
  2173.     mov    al,INTNUM_STOP
  2174.     int    DOS
  2175.     pop    ds
  2176. ;
  2177.     mov    dx,old_copy_ofs
  2178.     mov    ax,old_copy_sgm
  2179.     push    ds
  2180.     mov    ds,ax
  2181.     mov    ah,25h
  2182.     mov    al,INTNUM_COPY
  2183.     int    DOS
  2184.     pop    ds
  2185. ;
  2186.     pop    dx
  2187.     pop    ax
  2188.     popf
  2189.     ret
  2190. kbdlend    endp
  2191. code    ends
  2192.         end
  2193.