home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msk316src.zip / MSUIBM.ASM < prev    next >
Assembly Source File  |  1999-04-24  |  81KB  |  2,271 lines

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