home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msr313src.zip / msuibm.asm < prev    next >
Assembly Source File  |  1993-07-12  |  76KB  |  2,100 lines

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