home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msvp98b1.lzh / MSUP98.ASM < prev    next >
Assembly Source File  |  1991-12-06  |  91KB  |  2,247 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
  90.         extrn taklev:byte, comand:byte, flags:byte
  91.         extrn shkadr:word, stkadr:word, trans:byte, ttyact: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:word    ; 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. dosflg    db    0
  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. kbcodes    dw    80h        ; keyboard read codes, 80h=not inited
  379.  
  380. data    ends
  381.  
  382. ;                       Documentation
  383. ;Translating a key:
  384. ;   The translator is called to obtain keyboard input; it sends characters to
  385. ; the serial port through standard controlled echo procedures or invokes
  386. ; named procedures. It returns carry clear when its operation is completed
  387. ; for normal actions and carry set when Connect mode must be exited. When
  388. ; Connect mode is exited the just read char should be passed in Kbdflg
  389. ; to msster.asm for invoking actions such as Status, send a break,
  390. ; quit connect mode; system dependent procedure Term is responsible for this.
  391. ;
  392. ;  Principal procedures are -
  393. ;       msuinit         Initializes keyboard translator in this file when
  394. ;                       Kermit first begins. Installs dfkey and shkey as the
  395. ;                       procedures used for Set Key and Show Key. Sys Indep.
  396. ;                       Called from msx or msy init procs. System Independent.
  397. ;       keybd           Performs the translation, outputs chars to the serial
  398. ;                       port or invokes a Kermit action routine. Sys Indep.
  399. ;       dfkey           Defines a key's translation. Reads command line
  400. ;                       via Kermit's command parser comnd. System Independent.
  401. ;       shkey           Shows translation of a key. Requests user to push
  402. ;                       selected key. System Independent.
  403. ;
  404. ;       kbdinit         optional. Initializes the translation tables when
  405. ;                       Kermit starts up. Called by msuinit. System Dependent.
  406. ;       getkey          Performs the keyboard read and returns results in
  407. ;                       a standardized system independent format. Sys Depend.
  408. ;       postkey         called by active translator after obtaining a keycode.
  409. ;                       Used to provide extra local actions (keyclick) only
  410. ;                       in Connect mode (not during Set/Show key commands).
  411. ;                       Called by keybd. System dependent.
  412. ; Supporting system independent procedures are -
  413. ; shkfre (show string free space), tstkeyw (finds user's keyword in the verb
  414. ; table), insertst (insert string in buffer), remstr (delete string in buffer).
  415. ;
  416. ;   System dependent procedure Getkey reads a keycode (usually via a Bios
  417. ; call). On IBM compatible machines this yields <ah=scan code, al=ascii>
  418. ; for ordinary keys, or <ah=scan code, al=0> for special keys such as F1,
  419. ; or <ah=0, al=###> when Alt### is used.
  420. ; For any system, the canonical output form is the key's code in Keycode.
  421. ; Place the ascii code (or scan code if none) in byte Keycode and ancillary
  422. ; info (shift states plus marker bit for scan codes) in byte Keycode + 1.
  423. ;
  424. ;   Table Aliaskey is a list of scan code/ascii codes for keys which appear
  425. ; more than once on a keyboard. This list is examined to distinguish such
  426. ; aliased keys (those on an auxillary keypad) from an ordinary ascii key,
  427. ; and the aliased key is then referenced by its scan code rather than by
  428. ; the ordinary ascii code. Aliaskey is machine and keyboard dependent.
  429. ;
  430. ;    Procedure Keybd calls Getkey for the Keycode, checks list of translatable
  431. ; keys Keylist, and then either sends an ascii string (one or more characters)
  432. ; or invokes a Kermit action verb. List Dirlist indicates what kind of
  433. ; translation to do. Keybd is system independent but may contain system
  434. ; dependent special actions such as echoing keyclicks. Keybd calls system
  435. ; dependent procedure Postkey just after calling getkey so local actions
  436. ; such as keyclicks can be activated only during Connect mode operations.
  437. ;
  438. ;    Keylist is a packed but unordered list of 16 bit keycodes which need
  439. ; translation. The lower order byte holds a key code (ascii char or scan code)
  440. ; while the high byte holds a scan code marker bit (0 if ascii code in low
  441. ; byte) plus any ancillary keyboard information such as Control/Shift/Alt/Meta
  442. ; keys being held down; these are of use in Show Key presentations.
  443. ;    Dirlist parallels Keylist to provide the kind of translation, verb or
  444. ; string, in the two highest bits with the other bits holding either
  445. ; a single new replacement character or the item number in lists of verbs
  446. ; or strings. If neither verb nor strng type bits are set in a dirlist
  447. ; word then the translation is a single new character held in the lower
  448. ; eight bits of that dirlist word.
  449. ;
  450. ;    The number of key translations is assembly constant Maxkeys (def 128).
  451. ;    The maximum number of strings is assembly constant Maxstngs (def 64).
  452. ;    The maximum number of verbs is 256 and is set by building table Kverbs.
  453. ;
  454. ;   For verbs, use the Item number from the Director table Dirlist to select
  455. ; a procedure offset from the structured list Kverbs and jump to that offset.
  456. ; Most verb procedures return carry clear to stay within Connect mode.
  457. ; Verbs requiring exiting Connect mode return carry set and may set byte
  458. ; Kbdflg to a char code which will be read by msster.asm for activating a
  459. ; transient Kermit action such as send a break (Kbdflg = 'b').
  460. ; Kbdflg is stored in msster.asm (as zero initially, meaning ignore it).
  461. ; Action verb procedures are normally located in a system dependent file.
  462. ;
  463. ;   For multi-char strings, use Item number from Director table Dirlist to
  464. ; select a pointer to a string. The list of string pointers is Sptable
  465. ; (string pointer table) which holds the offset in the data segment of the
  466. ; strings stored in buffer Stbuf. In stbuf strings are held as: one byte of
  467. ; length of following text and then the text itself (permits embedded nulls).
  468. ;  Use Chrout to send each string character, and finally return from Keybd
  469. ; with carry clear.
  470. ;
  471. ;   For single character replacements obtain the new character from the lower
  472. ; order byte of Director table Dirlist. If the character is Kermit's present
  473. ; escape character return from Keybd carry set to leave connect mode.
  474. ; Otherwise, send the character via Chrout and return from Keybd carry clear.
  475.  
  476. ; Keylist table format:
  477. ;    7 bits   1 bit   8 bits
  478. ; +----------+----+------------+ scan bit = 1 if key's code is non-ascii
  479. ; | aux info |scan| key's code | aux info = system dependent, used only to
  480. ; +----------+----+------------+            help identify key
  481. ;
  482. ; Dirlist table format            v s   meaning
  483. ;   1   1      14 bits            0 0   copy out one byte translation
  484. ; +---+---+--------------------+  1 0   copy out multi-char string number Item
  485. ; | v | s | item # or new char |  0 1   do action verb number Item
  486. ; +---+---+--------------------+  1 1   (not used)
  487. ;
  488. ; Table kverbs is organized by macro mkeyw as -
  489. ;       kverbs  db      number of table entries
  490. ;       (each entry is in the form below:)
  491. ;               db      number of bytes in verbname
  492. ;               db      'verbname'              variable length
  493. ;               db      '$'                     for printing
  494. ;               dw      value                   offset of procedure
  495. ;
  496. ;
  497. ;   Dfkey defines a key to be itself (undefines it) or a single replacement
  498. ; character or a character string or a Kermit action verb. Dfkey requires
  499. ; a command line so that it may be invoked by Take files but can be forced
  500. ; to prompt an interactive user to push a key. Syntax is discussed below.
  501. ; Note that redefined keys have their old definitions cleared so that
  502. ; old string space is reclaimed automatically.
  503. ;
  504. ;   Shkey displays a key's definition and the user is asked to push the
  505. ; selected key. The free space for strings is always shown afterward. See
  506. ; below for syntax.
  507. ;
  508. ;   Kbdinit is an optional routine called when Kermit starts up. It fills in
  509. ; the translation tables with desirable default values to save having to
  510. ; use long mskermit.ini files. The default values are stored in a structured
  511. ; table similar to (but not the same as) Dfkey's command lines; the keycode
  512. ; values are preset by hand to 16 bit numbers.
  513.  
  514. ;Defining a key:
  515. ; Command is SET KEY <key ident><whitespace><definition>
  516. ;
  517. ; <key ident> is
  518. ;               a single ordinary ascii char or
  519. ;               the numerical equivalent of an ascii char or
  520. ;               a Scan Code written as a number or
  521. ;               keyword SCAN followed by a number.
  522. ;               ?       Displays help message.
  523. ;       Numbers and Binary codes are of the form
  524. ;               \123    a decimal number
  525. ;               \o456   an octal number         base letters o, d, x can be
  526. ;               \d213   a decimal number        upper or lower case
  527. ;               \x0d    a hex number
  528. ;               \{b###}  braces around above material following slash.
  529. ;
  530. ; <whitespace> is one or more spaces and or tabs.
  531. ;
  532. ; <definition> is
  533. ;       missing altogether which "undefines" a key.
  534. ;       \Kverb          for a Kermit action verb; upper or lower case K is ok
  535. ;       \{Kverb}        ditto. Verb is the name of an action verb.
  536. ;       text            a string with allowed embedded whitespace and embedded
  537. ;                       binary chars as above. This kind of string may not
  538. ;                       commence with sequences \K or \{K; use braces below.
  539. ;       {text}          string confined to material within but excluding
  540. ;                       the braces. Note, where the number of opening braces
  541. ;                       exceeds the number of closing braces the end of line
  542. ;                       terminates the string: {ab{}{{c}d ==> ab{}{{c}d
  543. ;                       but  {ab}{{c}d ==> ab.
  544. ;       ?               Displays help message and lists all action verbs.
  545. ;
  546. ;       If Set Key is given interactively, as opposed to within a Take
  547. ;       file, the system will prompt for inputs if none is on the command
  548. ;       line. The response to Push key to be defined cannot be edited.
  549. ;
  550. ;       Text which reduces to a single replacement character is put into a
  551. ;       table separate from the multi-character strings (maxstng of these).
  552. ;       A key may be translated into any single 8 bit code.
  553. ;
  554. ;       Comments can follow a Kermit action verb or a braced string; no
  555. ;       semicolon is required since all are stripped out by the Take file
  556. ;       reader before the defining text is seen by SET KEY.
  557. ;
  558. ;       The current Kermit escape character cannot be translated without
  559. ;       subtrafuge.
  560. ;
  561. ;       Examples:
  562. ;               Set Key q z
  563. ;                               makes key q send character z
  564. ;               Set Key \7 \27[0m
  565. ;                               makes key Control G send the four byte
  566. ;                               string  ESC [ 0 m
  567. ;               Set Key q
  568. ;                               undefines key q so it sends itself (q) again.
  569. ;               Set Key \2349 \kexit
  570. ;                               defines IBM Alt-X to invoke the leave connect
  571. ;                               mode verb "exit" (Kermit's escape-char ^] C).
  572. ;               Set Key \x0c Login \{x0d}myname\{x0d}mypass\x0d
  573. ;                               defines Control L to send the string
  574. ;                               Login <cr>myname<cr>mypass<cr>
  575. ;
  576. ; Alternative Set Key syntax for backward compatibility with previous versions
  577. ;       The same forms as above except the key identification number must
  578. ;       be decimal and must Not have a leading backslash. Example:
  579. ;       Set Key Scan 59 This is the F1 key
  580. ;
  581. ;       If the definition is omitted it may be placed on the following line;
  582. ;       if that line is also empty the key is undefined (defined as Self).
  583. ;       A warning message about obsolete syntax will be given followed by
  584. ;       the key's modern numerical value and new definition. Only "special"
  585. ;       keys (those not producing ascii codes) are compatible with this
  586. ;       translator.
  587. ;
  588. ;Showing a key:
  589. ; Command is SHOW KEY <cr>
  590. ; System prompts user to press a key and shows the definition plus the
  591. ; free space for strings. Query response results in showing all definitions.
  592. ;                       End Documentation
  593.  
  594. code    segment
  595.                 ; system independent external items
  596.         extrn   comnd:near, prompt:near                 ; in msscmd
  597.         extrn   strlen:near, prtscr:near                ; in mssfil
  598.         extrn   cnvlin:near, katoi:near, decout:near    ; in msster
  599.                 ; system dependent external items
  600.                 ; these are system dependent action verbs, in msxgen
  601.         extrn   beep:near, trnprs:near, sendbr:near
  602.         extrn   chrout:near, cstatus:near, cquit:near, cquery:near
  603.         extrn   klogon:near, klogof:near, kdos:near, snull:near, chang:near
  604.         extrn    trnmod:near
  605.  
  606.         extrn    pf1:near, pf2:near, pf3:near, pf4:near
  607.         extrn    kp0:near, kp1:near, kp2:near, kp3:near, kp4:near
  608.         extrn    kp5:near, kp6:near, kp7:near, kp8:near, kp9:near
  609.         extrn    kpmins:near, kpcoma:near, kpentr:near, kpdot:near
  610.         extrn    uparrw:near, dnarrw:near, lfarrw:near, rtarrw:near
  611.         extrn    decf6:near, decf7:near, decf8:near, decf9:near, decf10:near
  612.         extrn    decf11:near, decf12:near, decf13:near, decf14:near
  613.     extrn    dechelp:near, decdo:near
  614.     extrn    decf17:near, decf18:near, decf19:near, decf20:near
  615.     extrn    decfind:near, decinsert:near, decremove:near, decselect:near
  616.     extrn    decprev:near, decnext:near
  617.         extrn    keyinchg:near
  618.         extrn    vtchg:near, vtreset:near
  619.     extrn    upone:near, dnone:near, upscn:near, dnscn:near
  620.     extrn    gupone:near, gdnone:near
  621.     extrn    prtscn:near
  622.     extrn    vtrmac:near, vtsmac:near, extmacro:near
  623.  
  624.      extrn    s2jis:near, is_kanji1:near
  625.  
  626.         assume  cs:code, ds:data, es:data
  627.  
  628. ; Begin system independent Keyboard Translator code
  629.  
  630. ; MSUINIT performs Kermit startup initialization for this file.
  631. ; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
  632. ; are not initialized here then the older Set/Show Key procedures are called.
  633. MSUINIT PROC    NEAR                    ; call from msx/msy init code
  634.         call    kbdinit                 ; optional: init translator tables
  635.         mov     shkadr,offset shkey     ; declare keyboard translator present
  636.         mov     stkadr,offset dfkey     ; via Show and Set Key proc addresses
  637.         ret
  638. MSUINIT ENDP
  639.  
  640. ; Call Keybd to read a keyboard char (just returns carry clear if none) and
  641. ; 1) send the replacement string (or original char if not translated)
  642. ;    out the serial port, or
  643. ; 2) execute a Kermit action verb.
  644. ; Returns carry set if Connect mode is to be exited, else carry clear.
  645. ; Modifies registers ax and bx.
  646. KEYBD   PROC    NEAR                    ; active translator
  647.     mov    ttyact,1        ; doing single char output
  648.     cmp    stringcnt,0        ; any leftover string chars?
  649.     je    keybd0            ; e = no
  650.     jmp    keyst2            ; yes, finish string
  651. keybd0:    call    getkey            ; read keyboard
  652.     jnc    keybd1            ; nc = data available
  653.     jmp    keybdx            ; else just return carry clear
  654. keybd1:    call    postkey            ; call system dependent post processor
  655.         cmp     nkeys,0                 ; is number of keys defined = 0?
  656.         jz      keybd3                  ; z = none defined
  657.         push    di                      ; search keylist for this keycode
  658.         push    cx                      ; save some registers
  659.         push    es
  660.         mov     di,offset keylist       ; list of defined keycode words
  661.         mov     ax,keycode              ; present keycode
  662.         mov     cx,nkeys                ; number of words to examine
  663.         push    ds
  664.         pop     es                      ; make es:di point to data segment
  665.         cld
  666.         repne   scasw                   ; find keycode in list
  667.         pop     es                      ; restore regs
  668.         pop     cx
  669.         je      keybd1b                 ; e = found, work with present di
  670.         pop     di                      ; restore original di
  671.         test    keycode,scan            ; is this a scan code?
  672.         jz      keybd3                  ; z = no, it's ascii, use al as char
  673.         call    beep                    ; say key is a dead one
  674.         clc
  675.         ret                             ; and exit with no action
  676.  
  677. keybd1b:sub     di,2                    ; correct for auto increment
  678.         sub     di,offset keylist       ; subtract start of list ==> listptr
  679.         mov     ax,dirlist[di]          ; ax = contents of director word
  680.         pop     di                      ; restore original di
  681.                                         ; dispatch on Director code
  682.         test    ax,verb                 ; verb only?
  683.         jnz     keyvb                   ; e = yes
  684.         test    ax,strng                ; multi-char string only?
  685.         jnz     keyst                   ; e = yes, else single char & no xlat.
  686.                                         ;
  687.                                         ; do single CHAR output (char in al)
  688. keybd3: cmp     al,trans.escchr         ; Kermit's escape char?
  689.         je      keybd3a                 ; e = yes, handle separately
  690.     call    xltkey            ; do character set translation
  691.         call    chrout                  ; transmit the char
  692.         clc                             ; return success
  693.         ret
  694. keybd3a:stc                             ; set carry for jump to Quit
  695.         ret
  696.  
  697. keyvb:  and     ax,not(verb+strng)      ; VERB (ax=index, remove type bits)
  698.         mov     bx,offset kverbs        ; start of verb table
  699.         cmp     al,byte ptr [bx]        ; index > number of entries?
  700.         jae     keybdx                  ; ae = illegal, indices start at 0
  701.         inc     bx                      ; bx points to first entry
  702.         push    cx                      ; save reg
  703.         mov     cx,ax                   ; save the index in cx
  704.         inc     cx                      ; counter, indices start at 0
  705. keyvb1: mov     ax,[bx]            ; cnt value
  706.         add     ax,4                    ; skip text and value word
  707.         add     bx,ax                   ; look at next slot
  708.         loop    keyvb1                  ; walk to correct slot
  709.         sub     bx,2                    ; backup to value field
  710.     pop     cx                      ; restore reg
  711.         mov     bx,[bx]                 ; get value field of this slot
  712.         or      bx,bx                   ; jump address defined?
  713.         jz      keybdx                  ; z = no, skip the action
  714.         jmp     bx                      ; perform the function
  715.  
  716. keyst:    and    ax,not(verb+strng)    ; STRING (ax=index, remove type bits)
  717.     shl    ax,1            ; convert to word index
  718.     push    si            ; save working reg
  719.     mov    si,ax            ; word subscript in table
  720.     mov    si,sptable[si]        ; memory offset of selected string
  721.     xor    cx,cx            ; init string length to null
  722.     or    si,si            ; is there a string pointer present?
  723.     jz    keyst1            ; z = no, skip operation
  724.     cld                ; scan forward
  725.     mov    cx,[si]            ; get string length
  726.     add    si,2
  727. keyst1:    mov    stringcnt,cx
  728.     mov    stringptr,si
  729.     pop    si
  730.     jcxz    keybdx            ; z = null length
  731.  
  732. keyst2:    push    si
  733.     mov    si,stringptr        ; pointer to next string char
  734.     cld
  735.     lodsb                ; get new string char into al
  736.     pop    si
  737.     dec    stringcnt        ; string chars remaining
  738.     inc    stringptr
  739.     call    keysv            ; scan for embedded verbs
  740.     jc    keyst4            ; c = not found, al has string char
  741.     jmp    bx            ; perform the verb (bx = address)
  742. keyst4:    call    xltkey            ; do character set translation
  743.     cmp    stringcnt,0        ; last character?
  744.     je    keyst5            ; e = yes, stop grouping for nets
  745.     mov    ttyact,0        ; group output for networks
  746. keyst5:    jmp    chrout            ; send out the char in al
  747.  
  748. keybdx:    clc                ; return success (nothing to do)
  749.     ret
  750. KEYBD   ENDP
  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,cx        ; 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 carry set if failure.
  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.         or    byte ptr kbcodes,80h    ; say kbcodes not-initiated
  861.         mov     dx,offset tranbuf       ; our work space
  862.         mov     word ptr tranbuf,0      ; insert terminator
  863.         mov     bx,offset dfhelp1       ; first help message
  864.         mov     ah,cmword               ; parse a word
  865.         call    comnd                   ; get key code or original ascii char
  866.     mov    cl,taklev        ; reading from Take file
  867.         mov     msutake,cl              ; save here
  868.         or      ax,ax                   ; any text given?
  869.         jnz     dfkey12                 ; nz = yes, so don't consider prompts
  870.                                         ; interactive key request
  871.         cmp     taklev,0                ; in a Take file?
  872.         je      dfkey10                 ; e = no, prompt for keystroke
  873.         jmp     dfkey0                  ;  else say bad syntax
  874. dfkey10:mov     ah,prstr
  875.         mov     dx,offset dfaskky       ; ask for key to be pressed
  876.         int     dos
  877. dfkey11:call    getkey                  ; read key ident from keyboard
  878.         jc      dfkey11                 ; c = no response, wait for keystroke
  879.         mov     ah,prstr                ; display cr/lf
  880.         mov     dx,offset crlf
  881.         int     dos
  882.         call    shkey0                  ; show current definition (in SHKEY)
  883.         jmp     dfkey1e                 ; prompt for and process definition
  884.  
  885. dfkey12:                                ; Look for word SCAN and ignore it
  886.         mov     dx,word ptr tranbuf     ; get first two characters
  887.         or      dx,2020h                ; map upper to lower case
  888.         cmp     dx,'cs'                 ; first two letters of word "scan"?
  889.         je      dfkey                   ; e = yes, skip the word
  890.         cmp     dx,'lc'                 ; first two letters of word "clear"?
  891.     je    dfkey15            ; e = yes, reinit keyboard [2.31]
  892.     cmp    dx,'fo'            ; first two letters of "off"
  893.     je    dfkey13            ; e = yes, use DOS keyboard calls
  894.     cmp    dx,'no'            ; first two letters of "on"
  895.     je    dfkey13            ; e = yes, use standard kbd calls
  896. ; IBM    cmp    dx,'kl'            ; first two letters of "lk" (LK250)?
  897. ; IBM    je    dfkey13            ; e = yes
  898.     cmp    ax,1            ; number of characters received
  899.     jbe    dfkey12a        ; be = stay here
  900.     jmp    dfkey1            ; a = more than one, decode
  901. dfkey12a:mov    ah,byte ptr tranbuf    ; get the single char
  902.     mov    byte ptr keycode,ah    ; store as ascii keycode
  903.     jmp    dfkey1b            ; go get definition
  904. dfkey13:push    dx            ; save command letters
  905.     mov    ah,cmeol        ; get end of line confirmation
  906.     call    comnd
  907.     pop    dx
  908.     jnc    dfkey14            ; nc = success
  909.     ret
  910. dfkey14:mov    al,0ffh            ; set DOS keyboard read flag
  911.     cmp    dx,'fo'            ; first two letters of "off"
  912.     je    dfkey14a        ; e = yes, use DOS keyboard calls
  913.     xor    al,al            ; clear DOS keyboard read flag
  914.     cmp    dx,'no'            ; first two letters of "on"
  915.     je    dfkey14a        ; e = yes, use standard kbd calls
  916.     mov    ah,dosflg        ; get current flag
  917.     mov    dosflg,1        ; engage for chk250 test
  918. ;ibm    push    ax
  919. ;ibm    call    chk250            ; see if LK250 driver is present
  920. ;ibm    pop    ax
  921. ;ibm    mov    al,ah            ; recover current setting
  922. ;ibm    cmp    got250,0        ; did we find the driver?
  923. ;ibm    je    dfkey14a        ; e = no
  924. ;ibm    call    kbrest            ; and activiate it if so
  925.     mov    al,1            ; say LK250
  926. dfkey14a:mov    dosflg,al        ; store new keyboard flag
  927.     ret
  928.  
  929. dfkey15:mov    ah,cmeol
  930.     call    comnd            ; confirm request before proceeding
  931.     jnc    dfkeyc            ; nc = success
  932.     ret                ; failure
  933.  
  934. ;;jpn    cmp    dx,'ik'            ; KI:Kanji-in virtual key? [HF01]
  935. ;;jpn    jne    dfkey14            ; ne = no. [HF01]
  936. ;;jpn    mov    keycode,KI_code        ; store keycode [HF01]
  937. ;;jpn    jmp    dfkey1b            ; go get definition [HF01]
  938. ;;jpndfkey14:
  939. ;;jpn    cmp    dx,'ok'            ; KO:Kanji-out virtual key? [HF01]
  940. ;;jpn    jne    dfkey14a        ; ne = no. [HF01]
  941. ;;jpn    mov    keycode,KO_code        ; store keycode [HF01]
  942. ;;jpn    jmp    dfkey1b            ; go get definition [HF01]
  943. ;;jpndfkey14a:
  944. ;;jpn        cmp     ah,1                    ; number of characters received
  945. ;;jpn        ja      dfkey1                  ; a = more than one, decode
  946. ;;jpn        mov     ah,byte ptr tranbuf     ; get the single char
  947. ;;jpn        mov     byte ptr keycode,ah     ; store as ascii keycode
  948. ;;jpn        jmp     dfkey1b                 ; go get definition
  949.  
  950. dfkey0:    mov    dx,offset dfhelp1    ; say bad definition command
  951.     mov    ah,prstr
  952.     int    dos
  953.     stc                ; failure
  954.     ret
  955.  
  956. dfkeyc:                                 ; CLEAR key defs, restore startup defs
  957.         mov     cx,maxkeys              ; size of keycode tables
  958.         push    es                      ; save register
  959.         push    ds
  960.         pop     es                      ; make es point to data segment
  961.     xor    ax,ax            ; null, value to be stored
  962.         mov     di,offset dirlist       ; director table
  963.         cld
  964.         rep     stosw                   ; clear it
  965.         mov     cx,maxkeys        ; size of keycode tables
  966.         mov     di,offset keylist       ; keycode table
  967.         rep     stosw                   ; clear it
  968.         mov     cx,maxstng
  969.         mov     di,offset sptable       ; string pointer table
  970.         rep     stosw                   ; clear it
  971.         pop     es                      ; recover register
  972.     mov    strmax,offset stbuf    ; clear string buffer, free space ptr
  973.     mov    stbuf,0            ; first element of buffer 
  974.     mov    nkeys,0            ; clear number of defined keys
  975.     call    msuinit            ; restore startup definitions
  976.     clc                ; success
  977.     ret
  978.                                         ; Multi-char key identification
  979. dfkey1: mov     si,offset tranbuf       ; point to key ident text
  980.         cmp     byte ptr [si],'0'       ; is first character numeric?
  981.         jb      dfkey1a                 ; b = no
  982.         cmp     byte ptr [si],'9'       ; in numbers?
  983.         ja      dfkey1a                 ; a = no
  984.         mov     keycode,scan            ; setup keycode for scan value
  985.         mov     dx,si                   ; get length of string in cx
  986.         call    strlen
  987.         push    ds
  988.         pop     es                      ; make es point to data segment
  989.         push    si
  990.         add     si,cx                   ; point at string terminator
  991.         mov     di,si
  992.         inc     di                      ; place to store string (1 byte later)
  993.         inc     cx                      ; include null terminator
  994.         std                             ; work backward
  995.         rep     movsb                   ; move string one place later
  996.         cld
  997.         pop     si
  998.         mov     byte ptr [si],'\'       ; make ascii digits into \nnn form
  999.         mov     oldform,0ffh            ; set old form flag
  1000.         mov     dx,offset kwarnmsg      ; tell user this is old form
  1001.         mov     ah,prstr
  1002.         int     dos
  1003. dfkey1a:call    katoi                   ; convert ascii number to binary in ax
  1004.         jc      dfkey0                  ; c = no number converted
  1005.         or      keycode,ax              ; store in keycode
  1006.  
  1007. dfkey1b:                                ; Get Definition proper
  1008.         test    oldform,0ffh            ; old form Set Key active?
  1009.         jz      dfkey1f                 ; z = no
  1010.         mov     bx,offset tranbuf       ; get new definition on main cmd line
  1011.         mov     word ptr [bx],0         ; insert terminator
  1012.         mov     dx,offset dfhelp2       ; help for definition of key
  1013.         mov     ah,cmline               ; read rest of line into tranbuf
  1014.     call    comnd            ; allow null definitions
  1015.         or      ax,ax                   ; char count zero?
  1016.         jz      dfkey1e                 ; z = zero, prompt for definition
  1017.         jmp     dfkey1g                 ; process definition
  1018.  
  1019. dfkey1e:mov     ah,prstr
  1020.         mov     dx,offset crlf
  1021.         int     dos
  1022.         mov     dx,offset dfaskdf       ; prompt for definition string
  1023.         call    prompt                  ; Kermit prompt routine
  1024.         mov     comand.cmcr,1           ; permit bare carriage returns
  1025.     mov    comand.cmwhite,1    ; allow leading whitespace
  1026. dfkey1f:mov     bx,offset tranbuf       ; get new definition
  1027.         mov     word ptr [bx],0         ; insert terminator
  1028.         mov     dx,offset dfhelp2       ; help for definition of key
  1029.         mov     ah,cmline               ; read rest of line into tranbuf
  1030.     call    comnd
  1031.     jc    dfkey1x            ; exit now on ^C from user
  1032.     cmp    comand.cmcr,0        ; prompting for definition?
  1033.     je    dfkey1g            ; e = no, trim leading whitespace
  1034.     mov    comand.cmcr,0        ; turn off allowance for bare c/r's
  1035.     jmp    dfkey2            ; interactive, allow leading whitespace
  1036. dfkey1x:ret                ; failure exit
  1037.  
  1038. dfkey1g:push    ax            ; save count
  1039.     mov    ah,cmeol        ; get a confirm
  1040.     call    comnd
  1041.     pop    cx            ; string length
  1042.     jc    dfkey1x            ; none so declare parse error
  1043.     
  1044. dfkey2:                                 ; Examine translation
  1045.         mov     al,trans.escchr         ; current escape char (port dependent)
  1046.         cmp     al,byte ptr keycode     ; is this Kermit's escape char?
  1047.         jne     dfkey2a                 ; ne = no
  1048.         test    keycode,scan            ; see if scan code
  1049.         jnz     dfkey2a                 ; nz = scan, so not ascii esc char
  1050.     mov    dx,offset dfkoops    ; Oops! msg
  1051.     mov    ah,prstr        ; complain and don't redefine
  1052.     int    dos
  1053.     stc                ; failure
  1054.     ret
  1055.  
  1056. dfkey2a:push    di                      ; get a director code for this key
  1057.         push    cx
  1058.         mov     di,offset keylist       ; list of keycodes
  1059.         mov     cx,nkeys                ; number currently defined
  1060.         mov     ax,keycode              ; present keycode
  1061.         jcxz    dfkey2b                 ; cx = 0 means none defined yet
  1062.         cld
  1063.         push    ds
  1064.         pop     es
  1065.         repne   scasw                   ; is current keycode in the list?
  1066.         jne     dfkey2b                 ; ne = not in list
  1067.         sub     di,2                    ; correct for auto increment
  1068.         sub     di,offset keylist
  1069.         mov     listptr,di              ; list pointer for existing definition
  1070.         pop     cx
  1071.         pop     di
  1072.         jmp     dfkey3                  ; go process definition
  1073.  
  1074. dfkey2b:pop     cx                      ; key not currently defined so
  1075.         pop     di                      ;  make a new director entry for it
  1076.         mov     bx,nkeys                ; number of keys previously defined
  1077.         cmp     bx,maxkeys              ; enough space?
  1078.         jae     dfkey2c                 ; ae = no, complain
  1079.         shl     bx,1                    ; count words
  1080.         mov     listptr,bx              ; index into word list
  1081.         mov     ax,keycode              ; get key's code
  1082.         mov     keylist[bx],ax          ; store it in list of keycodes
  1083.         mov     dirlist[bx],0           ; clear the new director entry
  1084.         inc     nkeys                   ; new number of keys
  1085.         jmp     dfkey3                  ; go process definition
  1086.  
  1087. dfkey2c:mov     dx,offset keyfull       ; say key space is full already
  1088.         mov     ah,prstr
  1089.         int     dos
  1090.     stc                ; failure
  1091.     ret
  1092.  
  1093. ; listptr has element number in keylist or dirlist; keycode has key's code.
  1094.  
  1095. ; Parse new definition. First look for Kermit verbs as a line beginning
  1096. ; as \K or \{K. Otherwise, consider the line to be a string.
  1097. ; In any case, update the Director table for the new definition.
  1098.  
  1099. dfkey3: mov     brace,0                 ; assume not using braces
  1100.         mov     si,offset tranbuf       ; start of definition text
  1101.         cmp     byte ptr [si],'\'       ; starts with escape char?
  1102.         jne     dfkey5                  ; ne = no, so we have a string
  1103.         inc     si                      ; skip the backslash
  1104.         cmp     byte ptr [si],braceop   ; starts with \{?
  1105.         jne     dfkey3a                 ; ne = no
  1106.         inc     si                      ; skip the opening brace
  1107.         mov     brace,bracecl           ; expect closing brace
  1108. dfkey3a:cmp     byte ptr [si],'K'       ; starts with \{K or \K?
  1109.         je      dfkey3b                 ; e = yes
  1110.         cmp     byte ptr [si],'k'       ; starts as \{k or \k?
  1111.         jne     dfkey5                  ; ne = no, then it's a string
  1112. dfkey3b:inc     si                      ; yes, skip the K too
  1113.                                         ; Kermit action VERBS
  1114.         push    si                      ; save verb name start address
  1115. dfkey4:    cld
  1116.         lodsb                           ; scan til closing brace or w/s or end
  1117.         or    al,al            ; premature end?
  1118.         jz      dfkey4b                 ; z = yes, accept without brace
  1119.         cmp     al,brace                ; closing brace?
  1120.         je      dfkey4b                 ; e = yes
  1121.         cmp     al,spc                  ; white space or control char?
  1122.         ja      short dfkey4        ; a = no, so not at end yet
  1123. dfkey4b:mov     byte ptr[si-1],0        ; insert null terminator
  1124.         pop     si                      ; recover start address
  1125.         call    tstkeyw                 ; find keyword, kw # returned in kbtemp
  1126.         jc      dfkey4d                 ; c = no keyword found, complain
  1127.         call    remstr                  ; clear old string, if string
  1128.         mov     ax,kbtemp               ; save keyword number
  1129.         and     ax,not(verb+strng)      ; clear verb / string field
  1130.         or      ax,verb                 ; set verb ident
  1131.         mov     si,listptr
  1132.         mov     dirlist[si],ax          ; store info in Director table
  1133.         jmp     dfkey7                  ; show results and return success
  1134.  
  1135. dfkey4d:mov     dx,offset verbbad       ; say no such verb
  1136.         mov     ah,prstr
  1137.         int     dos
  1138.     stc                ; failure
  1139.     ret
  1140.  
  1141. ; Here we are left with the definition string; si points to its start, and
  1142. ; kbtemp holds its length (number of bytes). Null termination. If the string
  1143. ; begins with an opening brace it terminates on a matching closing brace
  1144. ; or the end of line, whichever occurs first. Trailing whitespace removed
  1145. ; before examining braces.
  1146. ; Null length strings mean define key as Self.
  1147.                                         ; STRING definitions
  1148. dfkey5: call    remstr                  ; first, clear old string, if any
  1149.         mov     si,offset tranbuf       ; si=source, di=dest, convert in-place
  1150.         mov     di,si
  1151.         call    cnvlin                  ; convert numbers, cx gets line length
  1152.         mov     si,offset tranbuf       ; provide address of new string
  1153.         cmp     cx,1                    ; just zero or one byte to do?
  1154.         jbe     dfkey6                  ; e = yes, do as a char
  1155.         call    insertst                ; insert new string, returns reg cx.
  1156.         jc      dfkey5h                 ; c = could not do insert
  1157.         mov     si,listptr              ; cx has type and string number
  1158.         mov     dirlist[si],cx          ; update Director table from insertst
  1159.         jmp     dfkey7                  ; show results and return success
  1160.  
  1161. dfkey5h:mov     dx,offset strbad        ; display complaint
  1162.         mov     ah,prstr
  1163.         int     dos
  1164.     stc                ; failure
  1165.     ret
  1166.  
  1167.                 ; define SINGLE CHAR replacement or CLEAR a key definition.
  1168.                 ; cx has char count 1 (normal) or 0 (to undefine the key).
  1169. dfkey6: jcxz    dfkey6c                 ; z = cx= 0, clear definition
  1170.         mov     al,byte ptr [si]        ; get first byte from definition
  1171.         xor     ah,ah                   ; set the type bits to Char
  1172.         mov     si,listptr
  1173.         mov     dirlist[si],ax          ; store type and key's new code
  1174.         jmp     dfkey7                  ; return success
  1175.  
  1176. dfkey6c:push    si                      ; clear a definition,
  1177.         push    di                      ; listptr points to current def
  1178.         mov     si,listptr              ; starting address to clear
  1179.         add     si,offset dirlist
  1180.         mov     di,si                   ; destination
  1181.         add     si,2                    ; source is next word
  1182.         mov     cx,nkeys                ; current number of keys defined
  1183.         add     cx,cx                   ; double for listptr being words
  1184.         sub     cx,listptr              ; cx = number of words to move
  1185.         shr     cx,1                    ; convert to actual number of moves
  1186.         jcxz    dfkey6d                 ; z = none, just remove last word
  1187.         push    es
  1188.         push    ds
  1189.         pop     es                      ; make es:di point to data segment
  1190.         cld
  1191.         push    cx                      ; save cx
  1192.         rep     movsw                   ; move down higher list items
  1193.         pop     cx
  1194.         mov     si,listptr              ; do keylist too, same way
  1195.         add     si,offset keylist
  1196.         mov     di,si
  1197.         add     si,2
  1198.         rep     movsw
  1199.         pop     es
  1200. dfkey6d:mov     si,nkeys                ; clear old highest list element
  1201.         shl     si,1                    ; address words
  1202.         mov     dirlist[si],0           ; null the element
  1203.         mov     keylist[si],0           ; null the element
  1204.         dec     nkeys                   ; say one less key defined now
  1205.         pop     di                      ; restore saved registers
  1206.         pop     si
  1207.  
  1208. dfkey7: mov     ah,msutake              ; Finish up. In a Take file?
  1209.         or      ah,taklev               ; or even directly
  1210.         or    ah,ah
  1211.         jz      dfkey7a                 ; z = no
  1212.         cmp     flags.takflg,0          ; echo Take commands?
  1213.         je      dfkey7b                 ; e = no
  1214. dfkey7a:mov     ah,prstr                ; display cr/lf
  1215.         mov     dx,offset crlf
  1216.         int     dos
  1217.         call    shkey0                  ; show new definition (in SHKEY)
  1218.         call    shkfre                  ; show free string space
  1219. dfkey7b:clc                ; return success
  1220.     ret
  1221. DFKEY   ENDP
  1222.  
  1223. ; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
  1224. ; command. Replaces obsolete procedure in msx---.
  1225. ; Prompts for a key and shows that key's (or all if ? entered) keycode,
  1226. ; definition, and the key definition free space remaining.
  1227.  
  1228. SHKEY   PROC    NEAR                    ; Show key's definition command
  1229.         mov     ah,cmeol                ; get a confirm
  1230.     call    comnd            ; ignore any additional text
  1231.         push    bx
  1232.         mov     dx,offset shkmsg1       ; ask for original key
  1233.         mov     ah,prstr
  1234.         int     dos
  1235.         or    byte ptr kbcodes,80h    ; say kbcodes not-initiated
  1236. shky0:  call    getkey                  ; read keyboard, output to keycode
  1237.         jc      shky0                   ; wait for a key (c = nothing there)
  1238.         cmp     byte ptr keycode,'?'    ; query for all keys?
  1239.         jne     shky0a                  ; ne = no, not a query
  1240.         test    keycode,scan            ; is this a scan code, vs ascii query?
  1241.         jz      shky0c                  ; z = no Scan, so it is a query
  1242.  
  1243. shky0a: mov     ah,prstr                ; show single key. Setup display
  1244.         mov     dx,offset crlf
  1245.         int     dos
  1246.         call    shkey0                  ; show just one key
  1247. shky0b: call    shkfre                  ; show free string space
  1248.         jmp     shkeyx                  ; exit
  1249.  
  1250. shky0c: mov     cx,nkeys                ; Show all keys. nkeys = number defined
  1251.         jcxz    shky0b                  ; z = none to show
  1252.         mov     si,offset keylist       ; list of definitions
  1253.         push    si                      ; save pointer
  1254. shky1:  pop     si                      ; recover pointer
  1255.         cld
  1256.         lodsw                           ; get a keycode
  1257.         push    si                      ; save pointer
  1258.         push    cx                      ; save counter
  1259.         mov     keycode,ax              ; save new keycode
  1260.         mov     ah,prstr
  1261.         mov     dx,offset crlf
  1262.         int     dos
  1263.         call    shkey0                  ; show this keycode
  1264.  
  1265.         pop     cx                      ; pause between screens, recover cntr
  1266.         push    cx                      ; save it again
  1267.         dec     cx                      ; number yet to be shown
  1268.         jcxz    shky1b                  ; z = have now shown all of them
  1269.         mov     ax,nkeys                ; number of defined keys
  1270.         sub     ax,cx                   ; minus number yet to be displayed
  1271.         xor     dx,dx                   ; clear extended numerator
  1272.         div     twelve                  ; two lines per definition display
  1273.         or      dx,dx                   ; remainder zero (12 defs shown)?
  1274.         jnz     shky1b                  ; nz = no, not yet so keep going
  1275.         mov     ah,prstr
  1276.         mov     dx,offset shkmsg3       ; "push any key to continue" msg
  1277.         int     dos
  1278. shky1a:    mov    ah,0bh            ; check console, check ^C
  1279.     int    dos
  1280.     cmp    flags.cxzflg,'C'    ; a ^C?
  1281.     je    shky1b            ; e = yes, quit
  1282.     or    al,al
  1283.     jz    shky1a            ; z = nothing
  1284.     call    getkey                  ; get any key
  1285.         jc      shky1a                  ; c = nothing at keyboard yet, wait
  1286. shky1b: pop     cx                      ; resume loop
  1287.     cmp    flags.cxzflg,'C'    ; a ^C?
  1288.     je    shky1c            ; e = yes, quit
  1289.         loop    shky1
  1290. shky1c:    pop     si                      ; clean stack
  1291.         call    shkfre                  ; show free string space
  1292.         jmp     shkeyx                  ; exit
  1293.  
  1294.                 ; show key worker routine, called from above
  1295.                                         ; SHKEY0 called by DFKEY just above
  1296. SHKEY0: test    keycode,scan            ; scan code?
  1297.         jz      shkey1                  ; z = no, regular ascii
  1298.  
  1299.                                         ; SCAN codes
  1300.         mov     dx,offset scanmsg       ; say Scan Code:
  1301.         mov     ah,prstr
  1302.         int     dos
  1303.         mov     ah,conout
  1304.         mov     dl,'\'                  ; add backslash before number
  1305.         int     dos
  1306.         mov     ax,keycode              ; get key's code again
  1307.         call    decout                  ; display 16 bit decimal keycode
  1308.         jmp     shkey2                  ; go get definition
  1309.  
  1310. shkey1: mov     dx,offset ascmsg        ; say ASCII CHAR
  1311.         mov     ah,prstr
  1312.         int     dos
  1313.         mov     dl,byte ptr keycode     ; get ascii code (al part of input)
  1314.         mov     ah,conout
  1315.         cmp     dl,spc                  ; control code?
  1316.         jae     shkey1a                 ; ae = no
  1317.         push    dx                      ; save char
  1318.         mov     dl,5eh                  ; show caret first
  1319.         int     dos
  1320.         pop     dx
  1321.         add     dl,'A'-1                ; ascii bias
  1322. shkey1a:cmp     dl,del                  ; DEL?
  1323.         jne     shkey1b                 ; ne = no
  1324.         mov     dl,'D'                  ; spell out DEL
  1325.         int     dos
  1326.         mov     dl,'E'
  1327.         int     dos
  1328.         mov     dl,'L'
  1329. shkey1b:int     dos
  1330.         mov     dl,spc                  ; add a couple of spaces
  1331.         int     dos
  1332.         int     dos
  1333.         mov     dl,'\'                  ; add backslash before number
  1334.         int     dos
  1335.         mov     ax,keycode              ; show 16 bit keycode in decimal
  1336.         call    decout                  ; and go get definiton
  1337.  
  1338.                                         ; Display defintion
  1339. shkey2: mov     dx,offset shkmsg2       ; intermediate part of reply
  1340.         mov     ah,prstr                ; " is defined as "
  1341.         int     dos
  1342.         push    di                      ; get a director code for this key
  1343.         push    cx
  1344.         mov     di,offset keylist       ; list of keycodes
  1345.         mov     cx,nkeys                ; number currently defined
  1346.         jcxz    shkey2a                 ; z = none
  1347.         mov     ax,keycode              ; present keycode
  1348.         push    ds
  1349.         pop     es                      ; use data segment for es:di
  1350.         cld
  1351.         repne   scasw                   ; is current keycode in the list?
  1352.         jne     shkey2a                 ; ne = not in list
  1353.         sub     di,2                    ; correct for auto increment
  1354.         sub     di,offset keylist
  1355.         mov     listptr,di              ; list pointer for existing definition
  1356.         pop     cx
  1357.         pop     di
  1358.         jmp     shkey3                  ; go process definition
  1359.  
  1360. shkey2a:pop     cx
  1361.         pop     di
  1362.         mov     dx,offset noxmsg        ; say Self (no translation)
  1363.         mov     ah,prstr
  1364.         int     dos
  1365.         ret                             ; return to main show key loop
  1366.  
  1367. shkey3:                                 ; translations, get kind of.
  1368.         mov     si,listptr
  1369.         test    dirlist[si],verb        ; defined as verb?
  1370.         jnz     shkey6                  ; nz = yes, go do that one
  1371.         test    dirlist[si],strng       ; defined as string?
  1372.         jz      shkey3a                 ; z = no
  1373.         jmp     shkey8                  ; yes, do string display
  1374. shkey3a:
  1375.         mov     dx,offset ascmsg        ; CHAR. say 'Ascii char:'
  1376.         mov     ah,prstr
  1377.         int     dos
  1378.         mov     ax,dirlist [si]         ; get type and char
  1379.         mov     dl,al                   ; put char here for display
  1380.         push    ax                      ; save here too
  1381.         mov     ah,conout
  1382.         cmp     dl,spc                  ; control code?
  1383.         jae     shkey4                  ; ae = no
  1384.         push    dx
  1385.         mov     dl,5eh                  ; show caret
  1386.         int     dos
  1387.         pop     dx
  1388.         add     dl,'A'-1                ; add ascii bias
  1389. shkey4: cmp     dl,del                  ; DEL?
  1390.         jne     shkey4a                 ; ne = no
  1391.         mov     dl,'D'                  ; spell out DEL
  1392.         int     dos
  1393.         mov     dl,'E'
  1394.         int     dos
  1395.         mov     dl,'L'
  1396. shkey4a:int     dos
  1397.         mov     dl,spc                  ; add a couple of spaces
  1398.         mov     ah,conout
  1399.         int     dos
  1400.         int     dos
  1401.         mov     dl,'\'                  ; add backslash before number
  1402.         int     dos
  1403.         pop     ax                      ; recover char
  1404.         xor     ah,ah                   ; clear high byte
  1405.         call    decout                  ; show decimal value
  1406.         ret                             ; return to main show key loop
  1407.  
  1408. shkey6: mov     ah,prstr                ; VERB
  1409.         mov     dx,offset verbmsg       ; say 'verb'
  1410.         int     dos
  1411.         mov     si,listptr              ; get verb index from director
  1412.         mov     dx,dirlist[si]
  1413.         and     dx,not(verb+strng)      ; remove type bits, leaves verb number
  1414.         mov     bx,offset kverbs        ; table of verbs & actions
  1415.         mov     al,byte ptr [bx]        ; number of keywords
  1416.         xor     ah,ah
  1417.         dec     ax
  1418.         mov     kwcnt,ax                ; save number of last one here
  1419.         cmp     dx,ax                   ; asking for more than we have?
  1420.         ja      shkeyx                  ; a = yes, exit bad
  1421.         inc     bx                      ; point to first slot
  1422.         xor     cx,cx                   ; current slot number
  1423. shkey6b:cmp     cx,dx                   ; this slot?
  1424.         je      shkey6c                 ; e = yes, print the text part
  1425.         ja      shkeyx                  ; a = beyond, exit bad
  1426.         mov     ax,[bx]            ; get cnt (keyword length)
  1427.         add     ax,4                    ; skip count and two byte value
  1428.         add     bx,ax                   ; bx = start of next keyword slot
  1429.         inc     cx                      ; current keyword number
  1430.         jmp     short shkey6b           ; try another
  1431. shkey6c:push    cx
  1432.     mov    cx,[bx]            ; length of definition
  1433.     add    bx,2            ; look at text field
  1434.         mov     di,bx                   ; offset for printing
  1435.         call    prtscr            ; print counted string
  1436.         mov     ah,conout
  1437.         mov     dl,spc                  ; add a couple of spaces
  1438.         int     dos
  1439.         int     dos
  1440.         mov     dl,'\'                  ; show verb name as \Kverb
  1441.         int     dos
  1442.         mov     dl,'K'
  1443.         int     dos
  1444.         call    prtscr            ; print counted string, again
  1445.     pop    cx
  1446.         ret                             ; return to main show key loop
  1447.  
  1448. shkey8: mov     ah,prstr                ; STRING
  1449.         mov     dx,offset strngmsg      ; say String:
  1450.         int     dos
  1451.         mov     si,listptr              ; get index from director
  1452.         mov     bx,dirlist[si]
  1453.         and     bx,not(verb+strng)      ; remove type bits
  1454.         shl     bx,1                    ; index words
  1455.         mov     si,sptable[bx]          ; table of string offsets
  1456.         mov     cx,word ptr [si]        ; get string length
  1457.     add    si,2            ; point to string text
  1458.         mov     ah,conout
  1459. shkey8a:cld
  1460.         lodsb                           ; get a byte
  1461.         cmp     al,spc                  ; control code?
  1462.         jae     shkey8b                 ; ae = no
  1463.         push    ax
  1464.         mov     dl,5eh                  ; show caret first
  1465.         int     dos
  1466.         pop     ax
  1467.         add     al,40h                  ; convert to printable for display
  1468. shkey8b:mov     dl,al
  1469.         int     dos                     ; display it
  1470.         loop    shkey8a                 ; do another
  1471.         ret                             ; return to main show key loop
  1472.  
  1473. shkeyx: pop     bx                      ; restore reg
  1474.     clc                ; return success
  1475.     ret
  1476. SHKEY   ENDP
  1477.  
  1478. ;;;     keyboard translator local support procedures, system independent
  1479.  
  1480. ; Tstkeyw checks text word pointed to by si against table of keywords (pointed
  1481. ; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
  1482. ; Returns in kbtemp the number of the keyword and carry clear, or if failure
  1483. ; returns kbtemp zero and carry set.
  1484. ; Keyword structure is:         dw      cnt     (length of string 'word')
  1485. ;                               db      'word'  (keyword string)
  1486. ;                               dw      value   (value returned in bx)
  1487. ; Make these with macro mkeyw such as   mkeyw 'test',15   with the list of
  1488. ; such keywords headed by a byte giving the number of keywords in the list.
  1489. tstkeyw proc    near
  1490.         push    ax
  1491.         push    cx
  1492.         push    si
  1493.         mov     verblen,0               ; verblen will hold verb length
  1494.         push    si                      ; save user's verb pointer
  1495. tstkw1: cld
  1496.         lodsb                           ; get a verb character
  1497.         cmp     al,spc                  ; verbs are all non-spaces and above
  1498.         jbe     tstkw2                  ; be = done (space or control char)
  1499.         inc     verblen                 ; count verb length
  1500.         jmp     short tstkw1            ; printable char, look for more
  1501. tstkw2: pop     si                      ; pointer to verb
  1502.         mov     bx,offset kverbs        ; table of Kermit verb keywords
  1503.         mov     al,byte ptr [bx]        ; number of keywords
  1504.         xor     ah,ah
  1505.         mov     kwcnt,ax                ; save number of keywords here
  1506.         inc     bx                      ; point bx to first slot
  1507.         mov     kbtemp,0                ; remember which keyword
  1508.  
  1509. tstkw3:                                 ; match table keyword and text word
  1510.         mov     cx,verblen              ; length of user's verb
  1511.         cmp     [bx],cx            ; compare length vs table keyword
  1512.         jne     tstkw4                  ; ne = not equal lengths, try another
  1513.         push    si                      ; lengths match, how about spelling?
  1514.         push    bx
  1515.     add    bx,2            ; point at start of keyword
  1516. tstkw3a:mov     ah,byte ptr [bx]        ; keyword char
  1517.         mov     al,byte ptr [si]        ; text char
  1518.         cmp     ah,'A'
  1519.         jb      tstkw3b                 ; b = control chars
  1520.         cmp     ah,'Z'
  1521.         ja      tstkw3b                 ; a = not upper case alpha
  1522.         add     ah,'a'-'A'              ; convert upper case to lower case
  1523. tstkw3b:cmp     al,'A'
  1524.         jb      tstkw3c
  1525.         cmp     al,'Z'
  1526.         ja      tstkw3c
  1527.         add     al,'a'-'A'              ; convert upper case to lower case
  1528. tstkw3c:cmp     al,ah                   ; test characters
  1529.         jne     tstkw3d                 ; ne = no match
  1530.         inc     si                      ; move to next char
  1531.         inc     bx
  1532.         loop    tstkw3a                 ; loop through entire length
  1533. tstkw3d:pop     bx
  1534.         pop     si
  1535.         jcxz    tstkw5                  ; z: cx = 0, exit with match;
  1536.                                         ;  else select next keyword
  1537. tstkw4: inc     kbtemp                  ; number of keyword to test next
  1538.         mov     cx,kbtemp
  1539.         cmp     cx,kwcnt                ; all done? Recall kbtemp starts at 0
  1540.         jae     tstkwx                  ;ae = exhausted search, unsuccessfully
  1541.         mov     ax,[bx]            ; cnt (keyword length from macro)
  1542.         add     ax,4                    ; skip over count and two byte value
  1543.         add     bx,ax                   ; bx = start of next keyword slot
  1544.         jmp     tstkw3                  ; do another comparison
  1545.  
  1546. tstkw5:                                 ; get action pointer
  1547.         mov     ax,[bx]            ; cnt (keyword length from macro)
  1548.         add     ax,2                    ; skip over count
  1549.         add     bx,ax                   ; now bx points to dispatch value
  1550.         mov     bx,[bx]                 ; bx holds dispatch value
  1551.         clc                             ; carry clear for success
  1552.         jmp     short tstkwxx           ; exit
  1553.         ret
  1554. tstkwx: xor     bx,bx                   ; exit when no match
  1555.         mov     kbtemp,bx               ; make verb number be zero too
  1556.         stc                             ; carry set for failure
  1557. tstkwxx:pop     si
  1558.         pop     cx
  1559.         pop     ax
  1560.         ret
  1561. tstkeyw endp
  1562.  
  1563. ; Insert asciiz string pointed to by si into string buffer stbuf.
  1564. ; Reg cx has string length upon entry.
  1565. ; Success: returns offset of first free byte (strmax) in string buffer stbuf,
  1566. ; cx = type and Index of new string, and carry clear.
  1567. ; Failure = carry set.
  1568. insertst proc   near
  1569.         push    bx
  1570.         push    dx
  1571.         push    si
  1572.         push    di
  1573.         push    kbtemp          ; save this variable too
  1574.         mov     dx,cx           ; save length of incoming string in dx
  1575.         mov     bx,offset sptable ; table of string offsets
  1576.         mov     kbtemp,0        ; slot number
  1577.         mov     cx,maxstng      ; number of entries, find an empty slot
  1578. insert1:cmp     word ptr[bx],0  ; slot empty?
  1579.         je      insert2         ; e = yes
  1580.         inc     kbtemp          ; remember slot number
  1581.         add     bx,2            ; look at next slot
  1582.         loop    insert1         ; keep looking
  1583.         jmp     short insert4   ; get here if no empty slots
  1584. insert2:                        ; see if stbuf has sufficient space
  1585.         mov     cx,dx           ; length of new string to cx
  1586.         mov     di,strmax       ; offset of first free byte in stbuf
  1587.         add     di,cx           ; di = address where this string would end
  1588.         cmp     di,offset stbuf+stbuflen ; beyond end of buffer?
  1589.         jae     insert4         ; ae = yes, not enough room
  1590.         mov     di,strmax       ; point to first free slot in stbuf
  1591.         mov     [bx],di         ; fill slot with address offset of buffer
  1592.         push    es
  1593.         push    ds
  1594.         pop     es              ; point es:di to data segment
  1595.         cld
  1596.         mov    [di],cx        ; length of text for new string
  1597.         add    di,2        ; move to next storage slot
  1598.         rep     movsb           ; copy string text
  1599.         pop     es
  1600.         mov     strmax,di       ; offset of next free byte
  1601.         mov     cx,kbtemp       ; return new slot number with Director Index
  1602.         and     cx,not(strng+verb) ; clear type bits
  1603.         or      cx,strng        ; say type is multi-char string
  1604.         clc                     ; say success
  1605.         jmp     short insertx   ; exit
  1606. insert4:stc                     ; say no-can-do
  1607. insertx:pop     kbtemp
  1608.         pop     di
  1609.         pop     si
  1610.         pop     dx
  1611.         pop     bx
  1612.         ret
  1613. insertst endp
  1614.  
  1615. ; Remove (delete) string. Enter with listptr preset for director entry.
  1616. ; Acts only on existing multi-char strings; recovers freed space.
  1617. ; All registers preserved.
  1618. remstr  proc    near
  1619.         push    si
  1620.         mov     si,listptr              ; list pointer
  1621.         test    dirlist[si],strng       ; multi-char string?
  1622.         pop     si
  1623.         jnz     remst1                  ; nz = a multi-char string
  1624.         ret                             ; else do nothing
  1625. remst1: push    ax
  1626.         push    bx
  1627.         push    cx
  1628.         push    dx
  1629.         push    si
  1630.         mov     si,listptr
  1631.         mov     ax,dirlist[si]          ; Director table entry
  1632.         and     ax,not(strng+verb) ; clear type bits, leave string's pointer
  1633.         mov     dirlist[si],0           ; clear Director table entry
  1634.         shl     ax,1                    ; index words not bytes
  1635.         mov     si,offset sptable       ; list of string offsets in stbuf
  1636.         add     si,ax                   ; plus index = current slot
  1637.         mov     bx,[si]                 ; get offset of string to be deleted
  1638.         mov     dx,bx                   ; save in dx for later
  1639.         mov     cx,[bx]            ; get length of subject string
  1640.         add     cx,2            ; length word too, cx has whole length
  1641.         sub     strmax,cx       ; count space to be freed (adj end-of-buf ptr)
  1642.         mov     word ptr [si],0 ; clear sptable of subject string address
  1643.         push    cx                      ; save length of purged string
  1644.         push    di                      ; save di
  1645.         push    si
  1646.         push    es                      ; save es
  1647.         push    ds
  1648.         pop     es              ; setup es:di to be ds:offset of string
  1649.         mov     di,dx           ; destination = start address of purged string
  1650.         mov     si,dx           ; source = start address of purged string
  1651.         add     si,cx           ;  plus string length of purged string.
  1652.         mov     cx,offset stbuf+stbuflen ; 1 + address of buffer end
  1653.         sub     cx,si                   ; 1 + number of bytes to move
  1654.         dec     cx                      ; number of bytes to move
  1655.         jcxz    remst2                  ; z = none
  1656.         cld                             ; direction is forward
  1657.         rep     movsb                   ; move down preserved strings
  1658. remst2: pop     es                      ; restore regs
  1659.         pop     di
  1660.         pop     si
  1661.         pop     ax              ; recover length of purged string (was in cx)
  1662.         mov     bx,offset sptable       ; string pointer table
  1663.         mov     cx,maxstng              ; max mumber of entries
  1664. remst4: cmp     [bx],dx         ; does this entry occur before purged string?
  1665.         jbe     remst5          ; be = before or equal, so leave it alone
  1666.         sub     [bx],ax         ; recompute address (remove old string space)
  1667. remst5: add     bx,2                    ; look at next list entry
  1668.         loop    remst4                  ; do all entries in sptable
  1669.         pop     si
  1670.         pop     dx
  1671.         pop     cx
  1672.         pop     bx
  1673.         pop     ax
  1674.         ret
  1675. remstr  endp
  1676.  
  1677. shkfre  proc    near                    ; show free key & string defs & space
  1678.         push    ax                      ; preserves all registers.
  1679.         push    bx
  1680.         push    cx
  1681.         push    dx
  1682.         push    kbtemp
  1683.         mov     dx,offset fremsg
  1684.         mov     ah,prstr
  1685.         int     dos
  1686.         mov     ax,maxkeys              ; max number of key defs
  1687.         sub     ax,nkeys                ; number currently used
  1688.         call    decout                  ; show the value
  1689.         mov     ah,prstr
  1690.         mov     dx,offset kyfrdef       ; give key defs msg
  1691.         int     dos
  1692.         mov     bx,offset sptable       ; table of string pointers
  1693.         mov     cx,maxstng              ; number of pointers
  1694.         mov     kbtemp,0                ; number free
  1695. shkfr1: cmp     word ptr [bx],0         ; slot empty?
  1696.         jne     shkfr2                  ; ne = no
  1697.         inc     kbtemp                  ; count free defs
  1698. shkfr2: add     bx,2                    ; look at next slot
  1699.         loop    shkfr1                  ; do all of them
  1700.         mov     ax,kbtemp               ; number of free defs
  1701.         call    decout                  ; display
  1702.         mov     dx,offset stfrdef       ; say free string defs
  1703.         mov     ah,prstr
  1704.         int     dos
  1705.         mov     ax,offset stbuf+stbuflen ; 1 + last byte in stbuf
  1706.         sub     ax,strmax               ; offset of last free byte in stbuf
  1707.         call    decout
  1708.         mov     dx,offset stfrspc       ; give free space part of msg
  1709.         mov     ah,prstr
  1710.         int     dos
  1711.         pop     kbtemp
  1712.         pop     dx
  1713.         pop     cx
  1714.         pop     bx
  1715.         pop     ax
  1716.         ret
  1717. shkfre  endp
  1718.  
  1719. ; Initialize the keyboard tables at Kermit startup time. Optional procedure.
  1720. ; Requires kbdinlst to be configured with mkeyw macro in the form
  1721. ;       mkeyw   'definition',keytype*256+keycode
  1722. ; keytype is 0 for scan codes and non-zero for ascii.
  1723. ; Returns normally.
  1724. kbdinit proc    near                    ; read keyword kbdinlst and setup
  1725.     or    byte ptr kbcodes,80h    ; say kbcodes not-initiated
  1726.         push    ds                      ;  initial keyboard assignments.
  1727.         pop     es                      ; set es:di to data segment
  1728.         inc    taklev            ; pretend that we are in Take file
  1729. ;ibm    call    chk250            ;** LK250 support begin
  1730. ;ibm    cmp    got250,1        ;** is it installed?
  1731. ;ibm    jne    kbdini0            ;** ne = no
  1732. ;ibm    call    kbrest            ;** else initialize to DEC mode
  1733. ;ibm    mov    si,offset kb250lst    ;** load extensions
  1734. ;ibm    jmp    short kbdini1        ;** LK250 support end
  1735. kbdini0:mov     si,offset kbdinlst      ; start of list of definitions
  1736. kbdini1:mov     cx,[si]            ; cnt field (keyword length of macro)
  1737.         jcxz    kbdinix                 ; z = null cnt field = end of list
  1738.     add    si,2            ; look at text field
  1739.         mov     di,offset tranbuf       ; where defkey expects text
  1740.         cld
  1741.         rep     movsb                   ; copy cx chars to tranbuf
  1742.         mov     byte ptr [di],0         ; insert null terminator
  1743.         mov     ax,word ptr [si]        ; get value field
  1744.         mov     keycode,ax              ; set key ident value
  1745.         push    si
  1746.         call    dfkey2                  ; put dfkey to work
  1747.         pop     si
  1748.         add     si,2                    ; point to next entry
  1749.         jmp     kbdini1                 ; keep working
  1750. kbdinix:dec    taklev            ; reset Take file level
  1751. ;ibm    call    udkclear        ; clear User Definable Keys
  1752. ;ibm    mov    cx,40h            ; segment 40h
  1753. ;ibm    mov    es,cx
  1754. ;ibm    mov    cl,byte ptr es:[96h]    ; kbd_flag_3, Enhanced keyboard area
  1755. ;ibm    test    cl,10h            ; select Enhanced kbd presence bit
  1756. ;ibm    jz    kbdinx1            ; z = regular (88)
  1757. ;ibm    mov    keyboard,101        ; 101 = enhanced kbd
  1758. kbdinx1:ret
  1759. kbdinit endp
  1760. ;;;     End of System Independent Procedures
  1761.  
  1762. ;;;     Begin System Dependent Procedures
  1763.  
  1764. ans_keystr    proc    near
  1765. ; returns key definition strings.
  1766. ; inputs:
  1767. ;   ax scan code for the key
  1768. ; outputs:
  1769. ;   cx number of strings (may be zero)
  1770. ;   bx address of the string buffer
  1771. ;
  1772.     xor    cx,cx        ; clear counter
  1773.     cmp    nkeys,0
  1774.     jg    ans_keystr1
  1775.     jmp    ans_keystrex
  1776. ans_keystr1:
  1777.     push    di                      ; search keylist for this keycode
  1778.     push    cx                      ; save some registers
  1779.     push    es
  1780.     mov     di,offset keylist       ; list of defined keycode words
  1781.     mov     cx,nkeys                ; number of words to examine
  1782.     push    ds
  1783.     pop     es                      ; make es:di point to data segment
  1784.     cld
  1785.     repne   scasw                   ; find keycode in list
  1786.     pop     es                      ; restore regs
  1787.     pop     cx
  1788.     je    ans_keystr2        ; e = found, work with present di
  1789.     pop     di            ; restore original di
  1790.     jmp    ans_keystrex
  1791. ans_keystr2:
  1792.     sub    di,2            ; correct for auto increment
  1793.     sub    di,offset keylist    ; subtract start of list ==> listptr
  1794.     mov    bx,offset dirlist    ; get the director address
  1795.     add    bx,di
  1796.     pop     di                      ; restore original di
  1797.                                         ; dispatch on Director code
  1798.     mov    ax,[bx]
  1799.         test    ax,verb                 ; verb only?
  1800.         jnz     ans_keystrex        ; nz = yes
  1801.     test    ax,strng        ; multi-char string only?
  1802.         jnz    ans_keystr3        ; nz = yes, else single char & no xlat.
  1803.      mov    cx,1            ; do single CHAR output (char in al)
  1804.      inc    bx
  1805.      jmp    ans_keystrex
  1806. ;
  1807. ans_keystr3:
  1808.     and    ax,not(verb+strng)    ; STRING (ax=index, remove type bits)
  1809.     shl    ax,1            ; convert to word index
  1810.     push    si            ; save working reg
  1811.     mov    si,ax            ; word subscript in table
  1812.     mov    bx,sptable[si]        ; memory offset of selected string
  1813.     pop    si
  1814.         cmp     bx,0            ; is there a string pointer present?
  1815.     je    ans_keystrex        ; e = no, skip operation
  1816.     mov    cx,[bx]            ; get string length byte to cx [kaneko]
  1817.     add    bx,2            ; adjust pointer [kaneko]
  1818. ;
  1819. ans_keystrex:
  1820.         ret
  1821. ans_keystr    endp
  1822.  
  1823. ; Read keyboard. System dependent.
  1824. ; Return carry set if nothing at keyboard.
  1825. ; If char present return carry clear with key's code in Keycode.
  1826. ; If key is ascii put that in the low byte of Keycode and clear bit Scan in
  1827. ; the high byte; otherwise, put the scan code in the lower byte and set bit
  1828. ; Scan in the high byte.
  1829. ; Bit Scan is set if key is not an ascii code.
  1830. ; Modifies register ax.
  1831. getkey  proc    near
  1832.     cmp    intrkey,0        ; Interrupt key pressed ?
  1833.     jne    getkey01        ; ne = Yes.
  1834.     jmp    getkey00        ; go to normal process
  1835. getkey01:
  1836.     push    bx
  1837.     mov    ax,intrkey
  1838.     dec    ax            ; index starts from 1
  1839.     shl    ax,1            ; item size in the table is 2 bytes
  1840.     mov    bx,offset intkey_tab    ; set table
  1841.     add    bx,ax            ; add index
  1842.     mov    ax,[bx]            ; get keycode
  1843.     mov    intrkey,0        ; clear index
  1844.     pop    bx
  1845.     jmp    getkey1
  1846. getkey00:
  1847.         mov     keycode,0
  1848.     cmp    keyin_dos,0        ; Keyinput using BIOS ?
  1849.     je    getkey0            ; e = yes, BIOS key input
  1850.     cmp    keyin_dos,1        ; Keyinput using CON ?
  1851.     jne    getkey02        ; ne = no
  1852.     jmp    getkey_con
  1853. getkey02:
  1854.     jmp    getkey_dos
  1855. ;
  1856. ; Keyinput using BIOS
  1857. ;
  1858. getkey0:
  1859.         mov     ah,sense_key
  1860.         int    bios
  1861.     cmp    bh,0
  1862.         jne     getky1                  ; ne = char available
  1863.     stc                ; carry set = nothing available
  1864.         jmp    getkyx            ; exit on no char available
  1865. getky1:
  1866.     mov    ah,read_key
  1867.     int    bios
  1868.     cmp    al,'^'            ; check SHIFT+'^'
  1869.     jne    getky1_2
  1870.     mov    ah,sense_shift
  1871.     int    bios
  1872.     test    al,1
  1873.     jz    getky1_1
  1874.     mov    ax,0C60h        ; Back quote
  1875.     jmp    getkey1
  1876. getky1_1:
  1877.     mov    ax,0C5Eh        ; '^'
  1878.     jmp    getkey1
  1879. getky1_2:
  1880.     cmp    ah,34h
  1881.     jb    getkey1
  1882.     cmp    ah,3Fh
  1883.     ja    getkey1
  1884.     push    dx
  1885.     mov    dx,ax            ; save code
  1886.     mov    ah,sense_shift        ; sense shift key
  1887.     int    bios
  1888.     test    al,10h            ; CTRL pressed ?
  1889.     jz    getky1_3        ; z = no
  1890.     add    dx,08000h
  1891.     jmp    getky1_4
  1892. getky1_3:
  1893.     test    al,1            ; SHIFT pressed ?
  1894.     jz    getky1_4        ; z = no
  1895.     add    dx,07000h
  1896. getky1_4:
  1897.     xchg    ax,dx
  1898.     pop    dx
  1899. getkey1:
  1900.         push    di                      ; check key (ax) for aliases
  1901.         push    cx
  1902.         push    es
  1903.         mov     di,offset aliaskey      ; list of aliased keys
  1904.         mov     cx,aliaslen             ; number of entries
  1905.         jcxz    getky2                  ; z = no entries
  1906.         push    ds
  1907.         pop     es                      ; make es:di point to data segment
  1908.         cld
  1909.         repne   scasw                   ; look for a match
  1910.         jne     getky2                  ; ne = not there
  1911.         mov     al,0                    ; force use of scan code (in ah)
  1912. getky2: pop     es
  1913.         pop     cx
  1914.         pop     di
  1915.         or      al,al                   ; scan code being returned?
  1916.         jnz     getky3                  ; nz = no
  1917.         cmp    ax,1A00h        ; CTRL-@ key ?
  1918.         je    getky3
  1919.         xchg    ah,al                   ; put scan code in ident area
  1920.         or      keycode,scan            ; set scan flag (vs ascii)
  1921. getky3: mov     byte ptr keycode,al     ; return key's code (usually ascii)
  1922.         clc                             ; carry clear = got a char
  1923. getkyx: ret
  1924. ;
  1925. ; Keyinput using MS-DOS console I/O + sense shift key
  1926. ;
  1927. getkey_con:
  1928.     push    dx
  1929.     mov    ah,6            ; direct console I/O
  1930.     mov    dl,0FFh            ; read
  1931.     int    dos
  1932.     jnz    getkey_con6
  1933.     jmp    getkey_con0
  1934. getkey_con6:
  1935.     cmp    al,0FFh            ; special key ?
  1936.     jne    getkey_con61        ; ne = no
  1937.     jmp    getkey_conS
  1938. getkey_con61:
  1939.     mov    dx,ax
  1940.     mov    ah,sense_shift        ; sense shift key
  1941.     int    bios
  1942.     xchg    ax,dx            ; now ax=code, dx=shift_key
  1943.     cmp    al,3Dh            ; is it '=' key ?
  1944.     jne    getkey_con4
  1945.     jmp    getkey_conK        ; goto keypad-key check
  1946. getkey_con4:
  1947.     cmp    al,2Ah
  1948.     jb    getkey_con3
  1949.     cmp    al,39h
  1950.     ja    getkey_con3
  1951.     jmp    getkey_conK        ; goto keypad-key check
  1952. getkey_con3:                ; Normal key
  1953.     mov    ah,0
  1954.     cmp    al,'^'
  1955.     jne    getkey_con5
  1956.     test    dl,1            ; SHIFT pressed ?
  1957.     jz    getkey_con2        ; z = no
  1958.     mov    al,60h            ; backquote
  1959.     jmp    getkey_con2
  1960. getkey_con5:
  1961.     cmp    al,20h
  1962.     ja    getkey_con2
  1963.     cmp    al,8            ; BS ?
  1964.     jne    getkey_con51        ; ne = No.
  1965.     mov    ah,22h            ; assume CTRL + H
  1966.     test    dl,10h            ; test CTRL key
  1967.     jnz    getkey_con2        ; nz = Pressed.
  1968.     mov    ah,0Eh            ; BS key
  1969.     jmp    getkey_con2
  1970. getkey_con51:
  1971.     cmp    al,9            ; TAB ?
  1972.     jne    getkey_con52        ; ne = No.
  1973.     mov    ah,17h            ; assume CTRL + I
  1974.     test    dl,10h            ; test CTRL key
  1975.     jnz    getkey_con2        ; nz = Pressed.
  1976.     mov    ah,0Fh            ; TAB key
  1977.     jmp    getkey_con2
  1978. getkey_con52:
  1979.     cmp    al,1Bh            ; ESC ?
  1980.     jne    getkey_con53        ; ne = No.
  1981.     mov    ah,1Bh            ; assume CTRL + [
  1982.     test    dl,10h            ; test CTRL key
  1983.     jnz    getkey_con2        ; nz = Pressed.
  1984.     mov    ah,0            ; ESC key
  1985.     jmp    getkey_con2
  1986. getkey_con53:
  1987.     cmp    al,0            ; NUL ?
  1988.     jne    getkey_con54        ; ne = No.
  1989.     mov    ah,1Ah            ; CTRL + @
  1990.     jmp    getkey_con2
  1991. getkey_con54:
  1992.     cmp    al,20h            ; SPACE ?
  1993.     jne    getkey_con55        ; ne = No.
  1994.     mov    ah,34h            ; set scan code
  1995.     test    dl,10h            ; test CTRL key
  1996.     jz    getkey_con2        ; z = Not Pressed.
  1997.     mov    ax,0B420h        ; CTRL-SPACE
  1998. getkey_con55:
  1999. getkey_con2:
  2000.     pop    dx
  2001.     jmp    getkey1
  2002. getkey_con0:
  2003.     pop    dx
  2004.     stc
  2005.     ret
  2006. ;
  2007. getkey_conS:
  2008.     mov    ah,6
  2009.     mov    dl,0FFh
  2010.     int    dos
  2011.     jnz    getkey_conS1
  2012.     jmp    getkey_con0
  2013. getkey_conS1:
  2014.     mov    ah,al
  2015.     xor    al,al
  2016.     cmp    ah,34h
  2017.     jb    getkey_conS4
  2018.     cmp    ah,3Fh
  2019.     ja    getkey_conS4
  2020.     push    dx
  2021.     mov    dx,ax            ; save code
  2022.     mov    ah,sense_shift        ; sense shift key
  2023.     int    bios
  2024.     test    al,10h            ; CTRL pressed ?
  2025.     jz    getkey_conS2        ; z = no
  2026.     add    dx,08000h
  2027.     jmp    getkey_conS3
  2028. getkey_conS2:
  2029.     test    al,1            ; SHIFT pressed ?
  2030.     jz    getkey_conS3        ; z = no
  2031.     add    dx,07000h
  2032. getkey_conS3:
  2033.     xchg    ax,dx
  2034.     pop    dx
  2035. getkey_conS4:
  2036.     jmp    getkey_con2
  2037. ;
  2038. getkey_conK:
  2039.     mov    bx,offset keypadgrp
  2040.     xor    ah,ah
  2041.     mov    dx,ax
  2042.     sub    ax,2Ah
  2043.     shl    ax,1
  2044.     add    bx,ax
  2045.     mov    ax,[bx]
  2046.     mov    bx,ax
  2047.     xor    bl,bl
  2048.     mov    ah,04h
  2049.     int    BIOS
  2050.     test    ax,bx
  2051.     jnz    getkey_conK1
  2052.     mov    ax,dx
  2053.     jmp    getkey_con2
  2054. getkey_conK1:
  2055.     mov    ax,dx
  2056.     mov    bx,offset keypadnum
  2057.     sub    ax,2Ah
  2058.     shl    ax,1
  2059.     add    bx,ax
  2060.     mov    ax,[bx]
  2061.     jmp    getkey_con2
  2062.  
  2063. getkey_dos:
  2064.     push    dx
  2065.     mov    ah,6            ; direct console I/O
  2066.     mov    dl,0FFh            ; read
  2067.     int    dos
  2068.     jnz    getkey_dos6
  2069.     jmp    getkey_dos0
  2070. getkey_dos6:
  2071.     cmp    al,0FFh            ; special key ?
  2072.     je    getkey_dos1        ; e = yes
  2073.     jmp    getkey_dos2
  2074. getkey_dos1:
  2075.     mov    ah,6
  2076.     mov    dl,0FFh
  2077.     int    dos
  2078.     jz    getkey_dos0
  2079.     mov    ah,al
  2080.     xor    al,al
  2081. getkey_dos2:
  2082.     pop    dx
  2083.     jmp    getkey1
  2084. getkey_dos0:
  2085.     pop    dx
  2086.     stc
  2087.     ret
  2088.  
  2089. getkey  endp
  2090.  
  2091. ; Return modified char code, depending on SET TERM CHAR-SET and active
  2092. ; Code Page. Enter and exit with char in AL.
  2093. xltkey    proc    near
  2094.     ret
  2095. xltkey    endp
  2096.  
  2097. postkey proc    near                    ; do sys dep action after reading
  2098.     test    vt100_flags,KEYCLICK_BIT
  2099.     je    postkey_ex
  2100.     push    ax
  2101.     push    cx
  2102. ;
  2103.     mov    al,06h
  2104.     out    37h,al            ; bell on
  2105.     mov    cx,1000h
  2106. postkey1:
  2107.     loop    postkey1
  2108. ;
  2109.     mov    al,07h
  2110.     out    37h,al            ; bell off
  2111. ;
  2112.     pop    cx
  2113.     pop    ax
  2114. postkey_ex:
  2115.         ret                             ; key during active translation
  2116. postkey endp
  2117.  
  2118. ; Interrupt routine for STOP and COPY keys
  2119.  
  2120. keyint_entry    proc    far
  2121. stop_int:
  2122.     push    ax
  2123.     push    ds
  2124. ;
  2125.     mov    ax,data
  2126.     mov    ds,ax
  2127.     cmp    intrkey,0
  2128.     jne    keyint_entry3
  2129.     mov    intrkey,1
  2130.     jmp    keyint_entry1
  2131. ;
  2132. copy_int:
  2133.     push    ax
  2134.     push    ds
  2135. ;
  2136.     mov    ax,data
  2137.     mov    ds,ax
  2138.     cmp    intrkey,0
  2139.     jne    keyint_entry3
  2140.     mov    intrkey,2
  2141. ;
  2142. keyint_entry1:
  2143. ;
  2144.     mov    ah,sense_shift
  2145.     int    bios
  2146.     test    al,10h            ; CTRL?
  2147.     jz    keyint_entry2
  2148.     add    intrkey,4
  2149.     jmp    keyint_entry3
  2150. keyint_entry2:
  2151.     test    al,1            ; SHIFT?
  2152.     jz    keyint_entry3
  2153.     add    intrkey,2
  2154. keyint_entry3:
  2155. ;
  2156.     pop    ds
  2157.     pop    ax
  2158.     iret
  2159. keyint_entry    endp
  2160.  
  2161. ; Keyboard local initialization routine
  2162.  
  2163. kbdlini    proc    near
  2164.     pushf
  2165.     cli                ; disable interrupt
  2166. ;
  2167.     push    ax
  2168.     push    bx
  2169.     push    dx
  2170.     push    es
  2171. ;
  2172.     mov    intrkey,0
  2173. ;
  2174.     mov    ah,35h            ; read interrupt vector
  2175.     mov    al,INTNUM_COPY        ; for COPY key interrupt
  2176.     int    DOS            ; system call
  2177.     mov    old_copy_ofs,bx        ; save vector
  2178.     mov    old_copy_sgm,es
  2179. ;
  2180.     mov    ah,35h            ; read interrupt vector
  2181.     mov    al,INTNUM_STOP        ; for STOP key interrupt
  2182.     int    DOS            ; system call
  2183.     mov    old_stop_ofs,bx        ; save vector
  2184.     mov    old_stop_sgm,es
  2185. ;
  2186.     mov    dx,offset copy_int
  2187.     mov    ax,cs
  2188.     push    ds
  2189.     mov    ds,ax
  2190.     mov    ah,25h
  2191.     mov    al,INTNUM_COPY
  2192.     int    DOS
  2193.     pop    ds
  2194. ;
  2195.     mov    dx,offset stop_int
  2196.     mov    ax,cs
  2197.     push    ds
  2198.     mov    ds,ax
  2199.     mov    ah,25h
  2200.     mov    al,INTNUM_STOP
  2201.     int    DOS
  2202.     pop    ds
  2203. ;
  2204.     pop    es
  2205.     pop    dx
  2206.     pop    bx
  2207.     pop    ax
  2208. ;
  2209.     popf
  2210.     ret
  2211. kbdlini    endp
  2212.  
  2213. ; keyboard local end routine
  2214.  
  2215. kbdlend    proc    near
  2216.     pushf
  2217.     cli                ; disable interrupt
  2218. ;
  2219.     push    ax
  2220.     push    dx
  2221. ;
  2222.     mov    dx,old_stop_ofs
  2223.     mov    ax,old_stop_sgm
  2224.     push    ds
  2225.     mov    ds,ax
  2226.     mov    ah,25h
  2227.     mov    al,INTNUM_STOP
  2228.     int    DOS
  2229.     pop    ds
  2230. ;
  2231.     mov    dx,old_copy_ofs
  2232.     mov    ax,old_copy_sgm
  2233.     push    ds
  2234.     mov    ds,ax
  2235.     mov    ah,25h
  2236.     mov    al,INTNUM_COPY
  2237.     int    DOS
  2238.     pop    ds
  2239. ;
  2240.     pop    dx
  2241.     pop    ax
  2242.     popf
  2243.     ret
  2244. kbdlend    endp
  2245. code    ends
  2246.         end
  2247.