home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
msr313src.zip
/
msu55x.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-16
|
72KB
|
1,632 lines
NAME msu55x
; File MSU55X.ASM
; Kermit system dependent module for Sanyo MBC-55x
; Sanyo mods by Robert W. Babcock and Joseph H. White
; For version which replaces the BIOS keycode translation table,
; use -dMODIFIED flag to MASM.
; Keyboard translator, by Joe R. Doupnik, Dec 1986
; with contributions from David L. Knoell.
; edit history:
; Last edit 20 April 1988, reconcile with IBM 2.30 release
; Revised Key definitions and removed Alias Keys June 2 1987 [jhw]
; 1 Jan 1988 version 2.30
include mssdef.h
public keybd, dfkey, shkey, msuinit
; some definitions
kbint equ 16h ; IBM, Bios keyboard interrupt
shift equ 200h ; IBM, synonym for right or left shift
control equ 400h ; IBM, synonym for control shift
alt equ 800h ; IBM, synonym for alt shift
maxkeys equ 200 ; maximum number of key definitions
maxstng equ 100 ; maximum number of multi-char strings
stbuflen equ 1000 ; length of string buffer (bytes)
verb equ 8000h ; dirlist flag: use verb action table
strng equ 4000h ; dirlist flag: use string action table
scan equ 100h ; keycode flag: code is scan not ascii
braceop equ 7bh ; opening curly brace
bracecl equ 7dh ; closing curly brace
datas segment public 'datas'
extrn taklev:byte, comand:byte, intake:byte, flags:byte
extrn shkadr:word, stkadr:word, trans:byte
; system dependent references
extrn vtemu:byte ; emulator data [jrd]
;;; System Independent local storage
tranbuf db 132 dup (?) ; 132 byte translator work buffer
crlf db cr,lf,'$'
dfhelp1 db cr,lf,' Enter key',27h,'s identification as a character',cr,lf
db ' or as its numerical equivalent \{b##} of ascii',cr,lf
db ' or as its scan code \{b##}'
db cr,lf,' or as SCAN followed by its scan code',cr,lf
db ' where b is O for octal, X for hex, or D for decimal'
db ' (default).',cr,lf,' Braces {} are optional.'
db cr,lf,' Follow the identification with the new definition.'
db cr,lf,' or CLEAR to restore initial key settings'
db cr,lf,' or ON (def) for Bios i/o or OFF to use DOS i/o.$' ;IBM
dfaskky db cr,lf,' Push key to be defined: $'
dfaskdf db ' Enter new definition: $'
verbbad db cr,lf,' No such verb',cr,lf,'$'
strbad db cr,lf,' Not enough space for new string',cr,lf,'$'
keyfull db cr,lf,' No more space to define keys',cr,lf,'$'
dfkopps db cr,lf,' Opps! That is Kermit',27h,'s Escape Char.'
db ' Translation is not permitted.',cr,lf,'$'
shkmsg1 db cr,lf,'Push key to be shown (? shows all): $'
shkmsg2 db ' decimal is defined as',cr,lf,'$'
shkmsg3 db cr,lf,'... more, push any key to continue ...$'
kwarnmsg db cr,lf,' Notice: this form of Set Key is obsolete$'
ascmsg db ' Ascii char: $'
scanmsg db ' Scan Code $'
strngmsg db ' String: $'
verbmsg db ' Verb: $'
noxmsg db ' Self, no translation.$'
fremsg db cr,lf,' Free space: $'
kyfrdef db ' key and $'
stfrdef db ' string definitions, $'
stfrspc db ' string characters.',cr,lf,'$'
; translation tables
keylist dw maxkeys dup (0) ; 16 bit keycodes, paralled by dirlist
dirlist dw maxkeys dup (0) ; director {v+s} + {index | new char}
sptable dw maxstng dup (0) ; list of asciiz string offsets
stbuf dw stbuflen dup (0) ; buffer for strings
strmax dw stbuf ; first free byte in stbuf
listptr dw ? ; item number for keylist and dirlist
nkeys dw 0 ; number of actively defined keys
keycode dw ? ; ascii/scan code for key
kbtemp dw ? ; scratch storage for translator
brace db ? ; brace detected flag byte
oldform db 0 ; old form Set Key, if non-zero
verblen dw ? ; length of user's verb (work temp)
kwcnt dw ? ; number of keywords (work temp)
msutake db ? ; if being run from take file or not
twelve dw 12d
dosflg db 0
;;; End System Independent Data Area
;;; System Dependent Data Area
; edit dfhelp2 to include nice list of verbs for this system.
dfhelp2 db cr,lf,' Enter either \Kverb for a Kermit action verb',cr,lf
db ' or a replacement string (single byte binary numbers are'
db ' \{b##})',cr,lf,' or push Return to undefine a key, ^C to'
db ' retain current definition.'
db cr,lf,' Braces {} are optional, and strings maybe enclosed in'
db ' them.',cr,lf,' Strings may not begin with the character'
db ' combinations of \k or \{k',cr,lf
db ' (start with a { brace instead).',cr,lf,lf
db ' Verbs are as follows. VT102 keys (arrows and keypad):',cr,lf
db ' uparr, dnarr, lfarr, rtarr, kpminus, kpcoma, kpdot, kpenter,'
db cr,lf
db ' Gold (same as PF1), PF1, PF2, PF3, PF4, kp0, ... kp9'
db cr,lf,' Kermit screen control and actions:',cr,lf
db ' upscn, dnscn, homscn, endscn, upone, dnone, prtscn, dump,'
db cr,lf
db ' logoff, logon, termtype, reset, modeline, break, lbreak,'
db cr,lf
db ' hangup, null (send one), DOS, help, status, exit'
db cr,lf,'$'
; Aliaskey: keys having aliases - same ascii code but more than one
; scan code, as on auxillary keypads. Use just scan codes with these.
; Alternative use: force ascii keys to report out just scan codes.
; Table format: high byte = scan code, low byte = ascii code.
; Contents are machine dependent.
aliaskey dw 0e08h ; backspace key
dw 4603h ; break key (distinguish from ^C
dw 320dh ; ^M (distinguish from RETURN)
dw 240ah ; ^J (distinguish from ^RETURN)
dw 1a1bh ; ^[ (distinguish from ESCAPE)
aliaslen equ ($-aliaskey) shr 1 ; number of words in aliaskey table
kverbs db 45 ; number of table entries below
mkeyw 'uparr',uparrw ; independent of ordering and case!
mkeyw 'dnarr',dnarrw ; mkeyw 'name',procedure entry point
mkeyw 'lfarr',lfarr
mkeyw 'rtarr',rtarr
mkeyw 'gold',pf1
mkeyw 'pf1',pf1
mkeyw 'pf2',pf2
mkeyw 'pf3',pf3
mkeyw 'pf4',pf4
mkeyw 'kp0',kp0
mkeyw 'kp1',kp1
mkeyw 'kp2',kp2
mkeyw 'kp3',kp3
mkeyw 'kp4',kp4
mkeyw 'kp5',kp5
mkeyw 'kp6',kp6
mkeyw 'kp7',kp7
mkeyw 'kp8',kp8
mkeyw 'kp9',kp9
mkeyw 'kpminus',kpminus
mkeyw 'kpcoma',kpcoma
mkeyw 'kpenter',kpenter
mkeyw 'kpdot',kpdot
mkeyw 'termtype',vtans52
mkeyw 'reset',vtinit
mkeyw 'dnscn',dnwpg
mkeyw 'upscn',upwpg
mkeyw 'endscn',endwnd
mkeyw 'homscn',homwnd
mkeyw 'upone',upone
mkeyw 'dnone',dnone
mkeyw 'prtscn',trnprs
mkeyw 'dump',dmpscn
mkeyw 'modeline',trnmod
mkeyw 'break',sendbr
mkeyw 'lbreak',sendbl
mkeyw 'hangup',chang
mkeyw 'null',snull
mkeyw 'logon',klogon
mkeyw 'logoff',klogof
mkeyw 'DOS',cdos
mkeyw 'help',cquery
mkeyw 'status',cstatus
mkeyw 'exit',cquit
; Initialization data.
;
; Revised definitions for Sanyo [begin jhw]
;
kbdinlst equ this byte ; Kermit IBM initialization time keyboard setup
mkeyw '\kgold',scan+59 ; F1 mkeyw 'definition',keycode
mkeyw '\kpf2',scan+60 ; F2
mkeyw '\kpf3',scan+61 ; F3
mkeyw '\kpf4',scan+62 ; F4
mkeyw '\kkp0',scan+93 ; ^0
mkeyw '\kkp1',scan+84 ; ^1
mkeyw '\kkp2',scan+85 ; ^2
mkeyw '\kkp3',scan+86 ; ^3
mkeyw '\kkp4',scan+87 ; ^4
mkeyw '\kkp5',scan+88 ; ^5
mkeyw '\kkp6',scan+89 ; ^6
mkeyw '\kkp7',scan+90 ; ^7
mkeyw '\kkp8',scan+91 ; ^8
mkeyw '\kkp9',scan+92 ; ^9
mkeyw '\kkpenter',scan+63 ; F5
mkeyw '\kkpcoma',scan+101 ; ^,
mkeyw '\kkpminus',scan+103 ; ^/
mkeyw '\kkpdot',scan+102 ; ^.
mkeyw '\kuparr',scan+72 ; VT100 cursor keys (arrows)
mkeyw '\kdnarr',scan+80
mkeyw '\klfarr',scan+75
mkeyw '\krtarr',scan+77
mkeyw '\kupscn',scan+73 ; PgUp Kermit screen roll back keys
mkeyw '\kdnscn',scan+81 ; PgDn
mkeyw '\khomscn',scan+71 ; Home
mkeyw '\kendscn',scan+79 ; End
ifdef MODIFIED
mkeyw '\kupone',scan+134 ; Ctrl Control Pg-Up one line scrolls
else
mkeyw '\kupone',scan+116 ; Ctrl Rt Arrow one line scrolls
endif
mkeyw '\kdnone',scan+118 ; Ctrl PgDn
mkeyw '\kmodeline',scan+64 ; F6
mkeyw '\ktermtype',scan+65 ; F7
mkeyw '\kreset',scan+66 ; F8
mkeyw '\kprtscn',scan+67 ; F9
mkeyw '\kdump',scan+117 ; Kermit Dump Screen Ctrl End
mkeyw '\x7f',scan+83 ; Del key sends DEL
mkeyw '\x7f',scan+14 ; Backspace key sends DEL
mkeyw '\kexit',scan+45 ; Exit connect mode Cntl-shift-X
mkeyw '\kstatus',scan+31 ; Connect mode status Cntl-shift-S
mkeyw '\kbreak',scan+70 ; Send a Break Break key
mkeyw '\khelp',scan+35 ; Con. mode drop down menu Cntl-shift-H
mkeyw '\x0d' ,scan+50 ; ^m sends CR
mkeyw '\x0a' ,scan+36 ; ^j sends line feed
mkeyw '\x1b' ,scan+26 ; ^[ sends ESCAPE
dw 0 ; end of table marker
datas ends
; Documentation
;Translating a key:
; The translator is called to obtain keyboard input; it sends characters to
; the serial port through standard controlled echo procedures or invokes
; named procedures. It returns carry clear when its operation is completed
; for normal actions and carry set when Connect mode must be exited. When
; Connect mode is exited the just read char should be passed in Kbdflg
; to msster.asm for invoking actions such as Status, send a break,
; quit connect mode; system dependent procedure Term is responsible for this.
;
; Principal procedures are -
; msuinit Initializes keyboard translator in this file when
; Kermit first begins. Installs dfkey and shkey as the
; procedures used for Set Key and Show Key. Sys Indep.
; Called from msx or msy init procs. System Independent.
; keybd Performs the translation, outputs chars to the serial
; port or invokes a Kermit action routine. Sys Indep.
; dfkey Defines a key's translation. Reads command line
; via Kermit's command parser comnd. System Independent.
; shkey Shows translation of a key. Requests user to push
; selected key. System Independent.
;
; kbdinit optional. Initializes the translation tables when
; Kermit starts up. Called by msuinit. System Dependent.
; getkey Performs the keyboard read and returns results in
; a standardized system independent format. Sys Depend.
; postkey called by active translator after obtaining a keycode.
; Used to provide extra local actions (keyclick) only
; in Connect mode (not during Set/Show key commands).
; Called by keybd. System dependent.
; Supporting system independent procedures are -
; shkfre (show string free space), tstkeyw (finds user's keyword in the verb
; table), insertst (insert string in buffer), remstr (delete string in buffer).
;
; System dependent procedure Getkey reads a keycode (usually via a Bios
; call). On IBM compatible machines this yields <ah=scan code, al=ascii>
; for ordinary keys, or <ah=scan code, al=0> for special keys such as F1,
; or <ah=0, al=###> when Alt### is used.
; For any system, the canonical output form is the key's code in Keycode.
; Place the ascii code (or scan code if none) in byte Keycode and ancillary
; info (shift states plus marker bit for scan codes) in byte Keycode + 1.
;
; Table Aliaskey is a list of scan code/ascii codes for keys which appear
; more than once on a keyboard. This list is examined to distinguish such
; aliased keys (those on an auxillary keypad) from an ordinary ascii key,
; and the aliased key is then referenced by its scan code rather than by
; the ordinary ascii code. Aliaskey is machine and keyboard dependent.
;
; Procedure Keybd calls Getkey for the Keycode, checks list of translatable
; keys Keylist, and then either sends an ascii string (one or more characters)
; or invokes a Kermit action verb. List Dirlist indicates what kind of
; translation to do. Keybd is system independent but may contain system
; dependent special actions such as echoing keyclicks. Keybd calls system
; dependent procedure Postkey just after calling getkey so local actions
; such as keyclicks can be activated only during Connect mode operations.
;
; Keylist is a packed but unordered list of 16 bit keycodes which need
; translation. The lower order byte holds a key code (ascii char or scan code)
; while the high byte holds a scan code marker bit (0 if ascii code in low
; byte) plus any ancillary keyboard information such as Control/Shift/Alt/Meta
; keys being held down; these are of use in Show Key presentations.
; Dirlist parallels Keylist to provide the kind of translation, verb or
; string, in the two highest bits with the other bits holding either
; a single new replacement character or the item number in lists of verbs
; or strings. If neither verb nor strng type bits are set in a dirlist
; word then the translation is a single new character held in the lower
; eight bits of that dirlist word.
;
; The number of key translations is assembly constant Maxkeys (def 128).
; The maximum number of strings is assembly constant Maxstngs (def 64).
; The maximum number of verbs is 256 and is set by building table Kverbs.
;
; For verbs, use the Item number from the Director table Dirlist to select
; a procedure offset from the structured list Kverbs and jump to that offset.
; Most verb procedures return carry clear to stay within Connect mode.
; Verbs requiring exiting Connect mode return carry set and may set byte
; Kbdflg to a char code which will be read by msster.asm for activating a
; transient Kermit action such as send a break (Kbdflg = 'b').
; Kbdflg is stored in msster.asm (as zero initially, meaning ignore it).
; Action verb procedures are normally located in a system dependent file.
;
; For multi-char strings, use Item number from Director table Dirlist to
; select a pointer to a string. The list of string pointers is Sptable
; (string pointer table) which holds the offset in the data segment of the
; strings stored in buffer Stbuf. In stbuf strings are held as: one byte of
; length of following text and then the text itself (permits embedded nulls).
; Use Chrout to send each string character, and finally return from Keybd
; with carry clear.
;
; For single character replacements obtain the new character from the lower
; order byte of Director table Dirlist. If the character is Kermit's present
; escape character return from Keybd carry set to leave connect mode.
; Otherwise, send the character via Chrout and return from Keybd carry clear.
; Keylist table format:
; 7 bits 1 bit 8 bits
; +----------+----+------------+ scan bit = 1 if key's code is non-ascii
; | aux info |scan| key's code | aux info = system dependent, used only to
; +----------+----+------------+ help identify key
;
; Dirlist table format v s meaning
; 1 1 14 bits 0 0 copy out one byte translation
; +---+---+--------------------+ 1 0 copy out multi-char string number Item
; | v | s | item # or new char | 0 1 do action verb number Item
; +---+---+--------------------+ 1 1 (not used)
;
; Table kverbs is organized by macro mkeyw as -
; kverbs db number of table entries
; (each entry is in the form below:)
; db number of bytes in verbname
; db 'verbname' variable length
; db '$' for printing
; dw value offset of procedure
;
;
; Dfkey defines a key to be itself (undefines it) or a single replacement
; character or a character string or a Kermit action verb. Dfkey requires
; a command line so that it may be invoked by Take files but can be forced
; to prompt an interactive user to push a key. Syntax is discussed below.
; Note that redefined keys have their old definitions cleared so that
; old string space is reclaimed automatically.
;
; Shkey displays a key's definition and the user is asked to push the
; selected key. The free space for strings is always shown afterward. See
; below for syntax.
;
; Kbdinit is an optional routine called when Kermit starts up. It fills in
; the translation tables with desirable default values to save having to
; use long mskermit.ini files. The default values are stored in a structured
; table similar to (but not the same as) Dfkey's command lines; the keycode
; values are preset by hand to 16 bit numbers.
;Defining a key:
; Command is SET KEY <key ident><whitespace><definition>
;
; <key ident> is
; a single ordinary ascii char or
; the numerical equivalent of an ascii char or
; a Scan Code written as a number or
; keyword SCAN followed by a number.
; ? Displays help message.
; Numbers and Binary codes are of the form
; \123 a decimal number
; \o456 an octal number base letters o, d, x can be
; \d213 a decimal number upper or lower case
; \x0d a hex number
; \{b###} braces around above material following slash.
;
; <whitespace> is one or more spaces and or tabs.
;
; <definition> is
; missing altogether which "undefines" a key.
; \Kverb for a Kermit action verb; upper or lower case K is ok
; \{Kverb} ditto. Verb is the name of an action verb.
; text a string with allowed embedded whitespace and embedded
; binary chars as above. This kind of string may not
; commence with sequences \K or \{K; use braces below.
; {text} string confined to material within but excluding
; the braces. Note, where the number of opening braces
; exceeds the number of closing braces the end of line
; terminates the string: {ab{}{{c}d ==> ab{}{{c}d
; but {ab}{{c}d ==> ab.
; ? Displays help message and lists all action verbs.
;
; If Set Key is given interactively, as opposed to within a Take
; file, the system will prompt for inputs if none is on the command
; line. The response to Push key to be defined cannot be edited.
;
; Text which reduces to a single replacement character is put into a
; table separate from the multi-character strings (maxstng of these).
; A key may be translated into any single 8 bit code.
;
; Comments can follow a Kermit action verb or a braced string; no
; semicolon is required since all are stripped out by the Take file
; reader before the defining text is seen by SET KEY.
;
; The current Kermit escape character cannot be translated without
; subtrafuge.
;
; Examples:
; Set Key q z
; makes key q send character z
; Set Key \7 \27[0m
; makes key Control G send the four byte
; string ESC [ 0 m
; Set Key q
; undefines key q so it sends itself (q) again.
; Set Key \2349 \kexit
; defines IBM Alt-X to invoke the leave connect
; mode verb "exit" (Kermit's escape-char ^] C).
; Set Key \x0c Login \{x0d}myname\{x0d}mypass\x0d
; defines Control L to send the string
; Login <cr>myname<cr>mypass<cr>
;
; Alternative Set Key syntax for backward compatibility with previous versions
; The same forms as above except the key identification number must
; be decimal and must Not have a leading backslash. Example:
; Set Key Scan 59 This is the F1 key
;
; If the definition is omitted it may be placed on the following line;
; if that line is also empty the key is undefined (defined as Self).
; A warning message about obsolete syntax will be given followed by
; the key's modern numerical value and new definition. Only "special"
; keys (those not producing ascii codes) are compatible with this
; translator.
;
;Showing a key:
; Command is SHOW KEY <cr>
; System prompts user to press a key and shows the definition plus the
; free space for strings. Query response results in showing all definitions.
; End Documentation
code segment public 'code'
; system independent external items
extrn comnd:near, prompt:near ; in msscmd
extrn strlen:near ; in mssfil
extrn cnvlin:near, katoi:near, decout:near ; in msster
; system dependent external items
extrn beep:near, prtchr:near ; in msxibm &msyibm
extrn anskbi:near, vclick:near ; in mszibm
; these are system dependent action verbs, in msxibm & msyibm
extrn uparrw:near, dnarrw:near, rtarr:near, lfarr:near
extrn pf1:near, pf2:near, pf3:near, pf4:near, kp0:near, kp1:near
extrn kp2:near, kp3:near, kp4:near, kp5:near, kp6:near, kp7:near
extrn kp8:near, kp9:near, kpminus:near, kpcoma:near, kpenter:near
extrn kpdot:near
extrn chrout:near, cstatus:near, cquit:near, cquery:near
extrn vtans52:near, vtinit:near, dnwpg:near, upwpg:near
extrn endwnd:near, homwnd:near, upone:near, dnone:near, trnprs:near
extrn trnmod:near, sendbr:near, sendbl:near, dmpscn:near, snull:near
extrn chang:near, klogon:near, klogof:near, cdos:near
ifdef MODIFIED
extrn rbtabl:near, sbtabl:near ;[jhw]
endif
assume cs:code, ds:datas, es:datas
; Begin system independent Keyboard Translator code
; MSUINIT performs Kermit startup initialization for this file.
; Note, shkadr and stkadr are pointers tested by Set/Show Key calls. If they
; are not initialized here then the older Set/Show Key procedures are called.
MSUINIT PROC NEAR ; call from msx/msy init code
call kbdinit ; optional: init translator tables
mov shkadr,offset shkey ; declare keyboard translator present
mov stkadr,offset dfkey ; via Show and Set Key proc addresses
ret
MSUINIT ENDP
; Call Keybd to read a keyboard char (just returns carry clear if none) and
; 1) send the replacement string (or original char if not translated)
; out the serial port, or
; 2) execute a Kermit action verb.
; Returns carry set if Connect mode is to be exited, else carry clear.
; Modifies registers ax and bx.
KEYBD PROC NEAR ; active translator
call getkey ; read keyboard
jnc keybd1 ; nc = data available
jmp keybdx ; else just return carry clear
keybd1: call postkey ; call system dependent post processor
cmp nkeys,0 ; is number of keys defined = 0?
jz keybd3 ; z = none defined
push di ; search keylist for this keycode
push cx ; save some registers
push es
mov di,offset keylist ; list of defined keycode words
mov ax,keycode ; present keycode
mov cx,nkeys ; number of words to examine
push ds
pop es ; make es:di point to datas segment
cld
repne scasw ; find keycode in list
pop es ; restore regs
pop cx
je keybd1b ; e = found, work with present di
pop di ; restore original di
test keycode,scan ; is this a scan code?
jz keybd3 ; z = no, it's ascii, use al as char
call beep ; say key is a dead one
clc
ret ; and exit with no action
keybd1b:sub di,2 ; correct for auto increment
sub di,offset keylist ; subtract start of list ==> listptr
mov ax,dirlist[di] ; ax = contents of director word
pop di ; restore original di
; dispatch on Director code
test ax,verb ; verb only?
jnz keyvb ; e = yes
test ax,strng ; multi-char string only?
jnz keyst ; e = yes, else single char & no xlat.
;
; do single CHAR output (char in al)
keybd3: cmp al,trans.escchr ; Kermit's escape char?
je keybd3a ; e = yes, handle separately
call chrout ; transmit the char
clc ; return success
ret
keybd3a:stc ; set carry for jump to Quit
ret
keyvb: and ax,not(verb+strng) ; VERB (ax=index, remove type bits)
mov bx,offset kverbs ; start of verb table
cmp al,byte ptr [bx] ; index > number of entries?
jae keybdx ; ae = illegal, indices start at 0
inc bx ; bx points to first entry
push cx ; save reg
mov cx,ax ; save the index in cx
inc cx ; counter, indices start at 0
keyvb1: mov al,byte ptr [bx] ; cnt value
xor ah,ah
add ax,4 ; skip text and '?' and value word
add bx,ax ; look at next slot
loop keyvb1 ; walk to correct slot
sub bx,2 ; backup to value field
keyvb2: pop cx ; restore reg
mov bx,[bx] ; get value field of this slot
cmp bx,0 ; jump address defined?
je keybdx ; e = no, skip the action
jmp bx ; perform the function
keyst: and ax,not(verb+strng) ; STRING (ax=index, remove type bits)
shl ax,1 ; convert to word index
push si ; save working reg
mov si,ax ; word subscript in table
mov si,sptable[si] ; memory offset of selected string
cmp si,0 ; is there a string pointer present?
je keyst3 ; e = no, skip operation
cld ; scan forward
lodsb ; get string length byte
mov cl,al
xor ch,ch ; to cx for looping
jcxz keybdx ; z = null length
keyst2: lodsb ; get new string char into al
push si ; save si and cx around call
push cx
call chrout ; send out the char in al
pop cx ; recover regs
pop si
loop keyst2 ; loop through whole string
keyst3: pop si ; restore reg
keybdx: clc ; return success
ret
KEYBD ENDP
; SET KEY - define a key (procedure dfkey)
; SET KEY <key ident><whitespace><new meaning>
; Call from Kermit level. Returns as ret if failure or as rskp if success.
;
DFKEY PROC NEAR ; define a key as a verb or a string
mov keycode,0 ; clear keycode
mov oldform,0 ; say no old form Set Key yet
mov dx,offset tranbuf ; our work space
mov word ptr tranbuf,0 ; insert terminator
mov bx,offset dfhelp1 ; first help message
mov ah,cmfile ; parse a word
call comnd ; get key code or original ascii char
nop
nop
nop
mov al,intake ; reading from Take file indirectly
or al,taklev ; ditto, directly
mov msutake,al ; save here
or ah,ah ; any text given?
jnz dfkey12 ; nz = yes, so don't consider prompts
; interactive key request
cmp intake,0 ; in a Take file?
je dfkey10 ; e = no, prompt for keystroke
jmp dfkey0 ; else say bad syntax
dfkey10:mov ah,prstr
mov dx,offset dfaskky ; ask for key to be pressed
int dos
dfkey11:call getkey ; read key ident from keyboard
jc dfkey11 ; c = no response, wait for keystroke
mov ah,prstr ; display cr/lf
mov dx,offset crlf
int dos
call shkey0 ; show current definition (in SHKEY)
jmp dfkey1e ; prompt for and process definition
dfkey12: ; Look for word SCAN and ignore it
mov dx,word ptr tranbuf ; get first two characters
or dx,2020h ; map upper to lower case
cmp dx,'cs' ; first two letters of word "scan"?
je dfkey ; e = yes, skip the word
cmp dx,'lc' ; first two letters of word "clear"?
je dfkeyc ; e = yes, reinit keyboard
cmp dx,'fo' ; first two letters of "off"
je dfkey13 ; e = yes, use DOS keyboard calls
cmp dx,'no' ; first two letters of "on"
je dfkey14 ; e = yes, use standard kbd calls
cmp ah,1 ; number of characters received
ja dfkey1 ; a = more than one, decode
mov ah,byte ptr tranbuf ; get the single char
mov byte ptr keycode,ah ; store as ascii keycode
jmp dfkey1b ; go get definition
dfkey13:mov dosflg,0ffh ; set DOS keyboard read flag
jmp rskp
dfkey14:mov dosflg,0 ; clear DOS keyboard read flag
jmp rskp
dfkey0: mov dx,offset dfhelp1 ; say bad definition command
mov ah,prstr
int dos
jmp rskp
dfkeyc: ; CLEAR key defs, restore startup defs
mov cx,maxkeys ; size of keycode tables
push es ; save register
push ds
pop es ; make es point to datas segment
mov ax,0 ; null, value to be stored
mov di,offset dirlist ; director table
cld
rep stosw ; clear it
mov cx,maxkeys
mov di,offset keylist ; keycode table
rep stosw ; clear it
mov cx,maxstng
mov di,offset sptable ; string pointer table
rep stosw ; clear it
pop es ; recover register
mov strmax,offset stbuf ; clear string buffer, free space ptr
mov stbuf,0 ; first element of buffer
mov nkeys,0 ; clear number of defined keys
call msuinit ; restore startup definitions
jmp rskp
; Multi-char key identification
dfkey1: mov si,offset tranbuf ; point to key ident text
cmp byte ptr [si],'0' ; is first character numeric?
jb dfkey1a ; b = no
cmp byte ptr [si],'9' ; in numbers?
ja dfkey1a ; a = no
mov keycode,scan ; setup keycode for scan value
mov dx,si ; get length of string in cx
call strlen
push ds
pop es ; make es point to datas segment
push si
add si,cx ; point at string terminator
mov di,si
inc di ; place to store string (1 byte later)
inc cx ; include null terminator
std ; work backward
rep movsb ; move string one place later
cld
pop si
mov byte ptr [si],'\' ; make ascii digits into \nnn form
mov oldform,0ffh ; set old form flag
mov dx,offset kwarnmsg ; tell user this is old form
mov ah,prstr
int dos
dfkey1a:call katoi ; convert ascii number to binary in ax
jc dfkey0 ; c = no number converted
or keycode,ax ; store in keycode
dfkey1b: ; Get Definition proper
test oldform,0ffh ; old form Set Key active?
jz dfkey1f ; z = no
mov bx,offset tranbuf ; get new definition on main cmd line
mov word ptr [bx],0 ; insert terminator
mov dx,offset dfhelp2 ; help for definition of key
mov ah,cmtxt ; read rest of line into tranbuf
call comnd
nop ; allow null definitions
nop
nop
or ah,ah ; char count zero?
jz dfkey1e ; z = zero, prompt for definition
jmp dfkey1g ; process definition
dfkey1e:mov ah,prstr
mov dx,offset crlf
int dos
mov dx,offset dfaskdf ; prompt for definition string
call prompt ; Kermit prompt routine
mov comand.cmcr,1 ; permit bare carriage returns
dfkey1f:mov bx,offset tranbuf ; get new definition
mov word ptr [bx],0 ; insert terminator
mov dx,offset dfhelp2 ; help for definition of key
mov ah,cmtxt ; read rest of line into tranbuf
call comnd
jmp r ; exit now on ^C from user
nop
cmp comand.cmcr,0 ; prompting for definition?
je dfkey1g ; e = no, trim leading whitespace
mov comand.cmcr,0 ; turn off allowance for bare c/r's
jmp dfkey2 ; interactive, allow leading whitespace
dfkey1g:xchg ah,al ; put byte count in al
xor ah,ah ; clear high byte
mov kbtemp,ax ; and save count in kbtemp
mov ah,cmcfm ; get a confirm
call comnd
jmp r ; none so declare parse error
nop ; round out to three bytes
mov cx,kbtemp ; string length
jcxz dfkey2 ; z = empty string
push si
push di
mov si,offset tranbuf ; strip leading white space
dfkey1c:cld ; work forward
lodsb ; read string char into al
dec cx ; number of chars left to read
cmp al,' ' ; a space?
je dfkey1c ; e = yes, keep going
cmp al,tab ; tab?
je dfkey1c ; e = yes, keep going
dec si ; offset inc si in lodsb
add cx,2 ; include terminator, offset dec above
jcxz dfkey1d ; z = nothing to move
mov di,offset tranbuf ; destination is start of buffer
push ds
pop es
cld
rep movsb ; copy text part of string
dfkey1d:pop di
pop si
dfkey2: ; Examine translation
mov al,trans.escchr ; current escape char (port dependent)
cmp al,byte ptr keycode ; is this Kermit's escape char?
jne dfkey2a ; ne = no
test keycode,scan ; see if scan code
jnz dfkey2a ; nz = scan, so not ascii esc char
mov dx,offset dfkopps ; Opps! msg
mov ah,prstr ; complain and don't redefine
int dos
jmp rskp
dfkey2a:push di ; get a director code for this key
push cx
mov di,offset keylist ; list of keycodes
mov cx,nkeys ; number currently defined
mov ax,keycode ; present keycode
jcxz dfkey2b ; cx = 0 means none defined yet
cld
push ds
pop es
repne scasw ; is current keycode in the list?
jne dfkey2b ; ne = not in list
sub di,2 ; correct for auto increment
sub di,offset keylist
mov listptr,di ; list pointer for existing definition
pop cx
pop di
jmp dfkey3 ; go process definition
dfkey2b:pop cx ; key not currently defined so
pop di ; make a new director entry for it
mov bx,nkeys ; number of keys previously defined
cmp bx,maxkeys ; enough space?
jae dfkey2c ; ae = no, complain
shl bx,1 ; count words
mov listptr,bx ; index into word list
mov ax,keycode ; get key's code
mov keylist[bx],ax ; store it in list of keycodes
mov dirlist[bx],0 ; clear the new director entry
inc nkeys ; new number of keys
jmp dfkey3 ; go process definition
dfkey2c:mov dx,offset keyfull ; say key space is full already
mov ah,prstr
int dos
jmp rskp ; tell parser we are happy
; listptr has element number in keylist or dirlist; keycode has key's code.
; Parse new definition. First look for Kermit verbs as a line beginning
; as \K or \{K. Otherwise, consider the line to be a string.
; In any case, update the Director table for the new definition.
dfkey3: mov brace,0 ; assume not using braces
mov si,offset tranbuf ; start of definition text
cmp byte ptr [si],'\' ; starts with escape char?
jne dfkey5 ; ne = no, so we have a string
inc si ; skip the backslash
cmp byte ptr [si],braceop ; starts with \{?
jne dfkey3a ; ne = no
inc si ; skip the opening brace
mov brace,bracecl ; expect closing brace
dfkey3a:cmp byte ptr [si],'K' ; starts with \{K or \K?
je dfkey3b ; e = yes
cmp byte ptr [si],'k' ; starts as \{k or \k?
jne dfkey5 ; ne = no, then it's a string
dfkey3b:inc si ; yes, skip the K too
; Kermit action VERBS
push si ; save verb name start address
dfkey4: cld
lodsb ; scan til closing brace or w/s or end
cmp al,0 ; premature end?
je dfkey4b ; e = yes, accept without brace
cmp al,brace ; closing brace?
je dfkey4b ; e = yes
cmp al,spc ; white space or control char?
ja short dfkey4 ; a = no, so not at end yet
dfkey4b:mov byte ptr[si-1],0 ; insert null terminator
pop si ; recover start address
call tstkeyw ; find keyword, kw # returned in kbtemp
jc dfkey4d ; c = no keyword found, complain
call remstr ; clear old string, if string
mov ax,kbtemp ; save keyword number
and ax,not(verb+strng) ; clear verb / string field
or ax,verb ; set verb ident
mov si,listptr
mov dirlist[si],ax ; store info in Director table
jmp dfkey7 ; show results and return success
dfkey4d:mov dx,offset verbbad ; say no such verb
mov ah,prstr
int dos
jmp rskp
; Here we are left with the definition string; si points to its start, and
; kbtemp holds its length (number of bytes). Null termination. If the string
; begins with an opening brace it terminates on a matching closing brace
; or the end of line, whichever occurs first. Trailing whitespace removed
; before examining braces.
; Null length strings mean define key as Self.
; STRING definitions
dfkey5: call remstr ; first, clear old string, if any
mov si,offset tranbuf ; si=source, di=dest, convert in-place
mov di,si
call cnvlin ; convert numbers, cx gets line length
mov si,offset tranbuf ; provide address of new string
cmp cx,1 ; just zero or one byte to do?
jbe dfkey6 ; e = yes, do as a char
call insertst ; insert new string, returns reg cx.
jc dfkey5h ; c = could not do insert
mov si,listptr ; cx has type and string number
mov dirlist[si],cx ; update Director table from insertst
jmp dfkey7 ; show results and return success
dfkey5h:mov dx,offset strbad ; display complaint
mov ah,prstr
int dos
dfkeyx: jmp rskp
; define SINGLE CHAR replacement or CLEAR a key definition.
; cx has char count 1 (normal) or 0 (to undefine the key).
dfkey6: jcxz dfkey6c ; z = cx= 0, clear definition
mov al,byte ptr [si] ; get first byte from definition
xor ah,ah ; set the type bits to Char
mov si,listptr
mov dirlist[si],ax ; store type and key's new code
jmp dfkey7 ; return success
dfkey6c:push si ; clear a definition,
push di ; listptr points to current def
mov si,listptr ; starting address to clear
add si,offset dirlist
mov di,si ; destination
add si,2 ; source is next word
mov cx,nkeys ; current number of keys defined
add cx,cx ; double for listptr being words
sub cx,listptr ; cx = number of words to move
shr cx,1 ; convert to actual number of moves
jcxz dfkey6d ; z = none, just remove last word
push es
push ds
pop es ; make es:di point to datas segment
cld
push cx ; save cx
rep movsw ; move down higher list items
pop cx
mov si,listptr ; do keylist too, same way
add si,offset keylist
mov di,si
add si,2
rep movsw
pop es
dfkey6d:mov si,nkeys ; clear old highest list element
shl si,1 ; address words
mov dirlist[si],0 ; null the element
mov keylist[si],0 ; null the element
dec nkeys ; say one less key defined now
pop di ; restore saved registers
pop si
dfkey7: mov ah,msutake ; Finish up. In a Take file?
or ah,taklev ; or even directly
cmp ah,0
je dfkey7a ; e = no
cmp flags.takflg,0 ; echo Take commands?
je dfkey7b ; e = no
dfkey7a:mov ah,prstr ; display cr/lf
mov dx,offset crlf
int dos
call shkey0 ; show new definition (in SHKEY)
call shkfre ; show free string space
dfkey7b:jmp rskp ; return success
DFKEY ENDP
; SHOW KEY <cr> command. Call from Kermit level. Vectored here by SHOW
; command. Replaces obsolete procedure in msx---.
; Prompts for a key and shows that key's (or all if ? entered) keycode,
; definition, and the key definition free space remaining.
SHKEY PROC NEAR ; Show key's definition command
ifdef MODIFIED
call sbtabl ; redefine the keys in Sanyo BIOS [jhw]
endif
mov ah,cmcfm ; get a confirm
call comnd
nop ; ignore any additional text
nop
nop
push bx
mov dx,offset shkmsg1 ; ask for original key
mov ah,prstr
int dos
shky0: call getkey ; read keyboard, output to keycode
jc shky0 ; wait for a key (c = nothing there)
cmp byte ptr keycode,'?' ; query for all keys?
jne shky0a ; ne = no, not a query
test keycode,scan ; is this a scan code, vs ascii query?
jz shky0c ; z = no Scan, so it is a query
shky0a: mov ah,prstr ; show single key. Setup display
mov dx,offset crlf
int dos
call shkey0 ; show just one key
shky0b: call shkfre ; show free string space
jmp shkeyx ; exit
shky0c: mov cx,nkeys ; Show all keys. nkeys = number defined
jcxz shky0b ; z = none to show
mov si,offset keylist ; list of definitions
push si ; save pointer
shky1: pop si ; recover pointer
cld
lodsw ; get a keycode
push si ; save pointer
push cx ; save counter
mov keycode,ax ; save new keycode
mov ah,prstr
mov dx,offset crlf
int dos
call shkey0 ; show this keycode
pop cx ; pause between screens, recover cntr
push cx ; save it again
dec cx ; number yet to be shown
jcxz shky1b ; z = have now shown all of them
mov ax,nkeys ; number of defined keys
sub ax,cx ; minus number yet to be displayed
xor dx,dx ; clear extended numerator
div twelve ; two lines per definition display
or dx,dx ; remainder zero (12 defs shown)?
jnz shky1b ; nz = no, not yet so keep going
mov ah,prstr
mov dx,offset shkmsg3 ; "push any key to continue" msg
int dos
shky1a: call getkey ; get any key
jc shky1a ; c = nothing at keyboard yet, wait
shky1b: pop cx ; resume loop
loop shky1
pop si ; clean stack
call shkfre ; show free string space
jmp shkeyx ; exit
; show key worker routine, called from above
; SHKEY0 called by DFKEY just above
SHKEY0: test keycode,scan ; scan code?
jz shkey1 ; z = no, regular ascii
; SCAN codes
mov dx,offset scanmsg ; say Scan Code:
mov ah,prstr
int dos
mov ah,conout
mov dl,'\' ; add backslash before number
int dos
mov ax,keycode ; get key's code again
call decout ; display 16 bit decimal keycode
jmp shkey2 ; go get definition
shkey1: mov dx,offset ascmsg ; say ASCII CHAR
mov ah,prstr
int dos
mov dl,byte ptr keycode ; get ascii code (al part of input)
mov ah,conout
cmp dl,spc ; control code?
jae shkey1a ; ae = no
push dx ; save char
mov dl,5eh ; show caret first
int dos
pop dx
add dl,'A'-1 ; ascii bias
shkey1a:cmp dl,del ; DEL?
jne shkey1b ; ne = no
mov dl,'D' ; spell out DEL
int dos
mov dl,'E'
int dos
mov dl,'L'
shkey1b:int dos
mov dl,spc ; add a couple of spaces
int dos
int dos
mov dl,'\' ; add backslash before number
int dos
mov ax,keycode ; show 16 bit keycode in decimal
call decout ; and go get definiton
; Display defintion
shkey2: mov dx,offset shkmsg2 ; intermediate part of reply
mov ah,prstr ; " is defined as "
int dos
push di ; get a director code for this key
push cx
mov di,offset keylist ; list of keycodes
mov cx,nkeys ; number currently defined
jcxz shkey2a ; z = none
mov ax,keycode ; present keycode
push ds
pop es ; use datas segment for es:di
cld
repne scasw ; is current keycode in the list?
jne shkey2a ; ne = not in list
sub di,2 ; correct for auto increment
sub di,offset keylist
mov listptr,di ; list pointer for existing definition
pop cx
pop di
jmp shkey3 ; go process definition
shkey2a:pop cx
pop di
mov dx,offset noxmsg ; say Self (no translation)
mov ah,prstr
int dos
ret ; return to main show key loop
shkey3: ; translations, get kind of.
mov si,listptr
test dirlist[si],verb ; defined as verb?
jnz shkey6 ; nz = yes, go do that one
test dirlist[si],strng ; defined as string?
jz shkey3a ; z = no
jmp shkey8 ; yes, do string display
shkey3a:
mov dx,offset ascmsg ; CHAR. say 'Ascii char:'
mov ah,prstr
int dos
mov ax,dirlist [si] ; get type and char
mov dl,al ; put char here for display
push ax ; save here too
mov ah,conout
cmp dl,spc ; control code?
jae shkey4 ; ae = no
push dx
mov dl,5eh ; show caret
int dos
pop dx
add dl,'A'-1 ; add ascii bias
shkey4: cmp dl,del ; DEL?
jne shkey4a ; ne = no
mov dl,'D' ; spell out DEL
int dos
mov dl,'E'
int dos
mov dl,'L'
shkey4a:int dos
mov dl,spc ; add a couple of spaces
mov ah,conout
int dos
int dos
mov dl,'\' ; add backslash before number
int dos
pop ax ; recover char
xor ah,ah ; clear high byte
call decout ; show decimal value
ret ; return to main show key loop
shkey6: mov ah,prstr ; VERB
mov dx,offset verbmsg ; say 'verb'
int dos
mov si,listptr ; get verb index from director
mov dx,dirlist[si]
and dx,not(verb+strng) ; remove type bits, leaves verb number
mov bx,offset kverbs ; table of verbs & actions
mov al,byte ptr [bx] ; number of keywords
xor ah,ah
dec ax
mov kwcnt,ax ; save number of last one here
cmp dx,ax ; asking for more than we have?
ja shkeyx ; a = yes, exit bad
inc bx ; point to first slot
mov cx,0 ; current slot number
shkey6b:cmp cx,dx ; this slot?
je shkey6c ; e = yes, print the text part
ja shkeyx ; a = beyond, exit bad
mov al,byte ptr [bx] ; get cnt (keyword length)
xor ah,ah
add ax,4 ; skip over '$' and two byte value
add bx,ax ; bx = start of next keyword slot
inc cx ; current keyword number
jmp short shkey6b ; try another
shkey6c:inc bx ; look at text field
mov dx,bx ; offset for printing
mov ah,prstr
int dos
mov ah,conout
mov dl,spc ; add a couple of spaces
int dos
int dos
mov dl,'\' ; show verb name as \Kverb
int dos
mov dl,'K'
int dos
mov ah,prstr
mov dx,bx ; show name part again
int dos
ret ; return to main show key loop
shkey8: mov ah,prstr ; STRING
mov dx,offset strngmsg ; say String:
int dos
mov si,listptr ; get index from director
mov bx,dirlist[si]
and bx,not(verb+strng) ; remove type bits
shl bx,1 ; index words
mov si,sptable[bx] ; table of string offsets
mov cl,byte ptr [si] ; get string length byte
xor ch,ch
inc si ; point to string text
mov ah,conout
shkey8a:cld
lodsb ; get a byte
cmp al,spc ; control code?
jae shkey8b ; ae = no
push ax
mov dl,5eh ; show caret first
int dos
pop ax
add al,40h ; convert to printable for display
shkey8b:mov dl,al
int dos ; display it
loop shkey8a ; do another
ret ; return to main show key loop
shkeyx: pop bx ; restore reg
ifdef MODIFIED
shkeyz: call rbtabl ; reset to original bios key defs [jhw]
endif
jmp rskp ; return success
SHKEY ENDP
;;; keyboard translator local support procedures, system independent
; Tstkeyw checks text word pointed to by si against table of keywords (pointed
; to by kverbs, made by mkeyw macro); returns in bx either action value or 0.
; Returns in kbtemp the number of the keyword and carry clear, or if failure
; returns kbtemp zero and carry set.
; Keyword structure is: db cnt (length of string 'word')
; db 'word' (keyword string)
; db '$' (printing terminator)
; dw value (value returned in bx)
; Make these with macro mkeyw such as mkeyw 'test',15 with the list of
; such keywords headed by a byte giving the number of keywords in the list.
tstkeyw proc near
push ax
push cx
push si
mov verblen,0 ; verblen will hold verb length
push si ; save user's verb pointer
tstkw1: cld
lodsb ; get a verb character
cmp al,spc ; verbs are all non-spaces and above
jbe tstkw2 ; be = done (space or control char)
inc verblen ; count verb length
jmp short tstkw1 ; printable char, look for more
tstkw2: pop si ; pointer to verb
mov bx,offset kverbs ; table of Kermit verb keywords
mov al,byte ptr [bx] ; number of keywords
xor ah,ah
mov kwcnt,ax ; save number of keywords here
inc bx ; point bx to first slot
mov kbtemp,0 ; remember which keyword
tstkw3: ; match table keyword and text word
mov cx,verblen ; length of user's verb
cmp byte ptr [bx],cl ; compare length vs table keyword
jne tstkw4 ; ne = not equal lengths, try another
push si ; lengths match, how about spelling?
push bx
inc bx ; point at start of keyword
tstkw3a:mov ah,byte ptr [bx] ; keyword char
mov al,byte ptr [si] ; text char
cmp ah,'A'
jb tstkw3b ; b = control chars
cmp ah,'Z'
ja tstkw3b ; a = not upper case alpha
add ah,'a'-'A' ; convert upper case to lower case
tstkw3b:cmp al,'A'
jb tstkw3c
cmp al,'Z'
ja tstkw3c
add al,'a'-'A' ; convert upper case to lower case
tstkw3c:cmp al,ah ; test characters
jne tstkw3d ; ne = no match
inc si ; move to next char
inc bx
loop tstkw3a ; loop through entire length
tstkw3d:pop bx
pop si
jcxz tstkw5 ; z: cx = 0, exit with match;
; else select next keyword
tstkw4: inc kbtemp ; number of keyword to test next
mov cx,kbtemp
cmp cx,kwcnt ; all done? Recall kbtemp starts at 0
jae tstkwx ;ae = exhausted search, unsuccessfully
mov al,byte ptr [bx] ; cnt (keyword length from macro)
xor ah,ah
add ax,4 ; skip over '$' and two byte value
add bx,ax ; bx = start of next keyword slot
jmp tstkw3 ; do another comparison
tstkw5: ; get action pointer
mov al,byte ptr [bx] ; cnt (keyword length from macro)
xor ah,ah
add ax,2 ; skip over '$'
add bx,ax ; now bx points to dispatch value
mov bx,[bx] ; bx holds dispatch value
clc ; carry clear for success
jmp short tstkwxx ; exit
ret
tstkwx: xor bx,bx ; exit when no match
mov kbtemp,bx ; make verb number be zero too
stc ; carry set for failure
tstkwxx:pop si
pop cx
pop ax
ret
tstkeyw endp
; Insert asciiz string pointed to by si into string buffer stbuf.
; Reg cx has string length upon entry.
; Success: returns offset of first free byte (strmax) in string buffer stbuf,
; cx = type and Index of new string, and carry clear.
; Failure = carry set.
insertst proc near
push bx
push dx
push si
push di
push kbtemp ; save this variable too
mov dx,cx ; save length of incoming string in dx
mov bx,offset sptable ; table of string offsets
mov kbtemp,0 ; slot number
mov cx,maxstng ; number of entries, find an empty slot
insert1:cmp word ptr[bx],0 ; slot empty?
je insert2 ; e = yes
inc kbtemp ; remember slot number
add bx,2 ; look at next slot
loop insert1 ; keep looking
jmp short insert4 ; get here if no empty slots
insert2: ; see if stbuf has sufficient space
mov cx,dx ; length of new string to cx
mov di,strmax ; offset of first free byte in stbuf
add di,cx ; di = address where this string would end
cmp di,offset stbuf+stbuflen ; beyond end of buffer?
jae insert4 ; ae = yes, not enough room
mov di,strmax ; point to first free slot in stbuf
mov [bx],di ; fill slot with address offset of buffer
push es
push ds
pop es ; point es:di to datas segment
cld
mov byte ptr [di],cl ; length of text for new string
inc di ; move to next storage slot
rep movsb ; copy string text
pop es
mov strmax,di ; offset of next free byte
mov cx,kbtemp ; return new slot number with Director Index
and cx,not(strng+verb) ; clear type bits
or cx,strng ; say type is multi-char string
clc ; say success
jmp short insertx ; exit
insert4:stc ; say no-can-do
insertx:pop kbtemp
pop di
pop si
pop dx
pop bx
ret
insertst endp
; Remove (delete) string. Enter with listptr preset for director entry.
; Acts only on existing multi-char strings; recovers freed space.
; All registers preserved.
remstr proc near
push si
mov si,listptr ; list pointer
test dirlist[si],strng ; multi-char string?
pop si
jnz remst1 ; nz = a multi-char string
ret ; else do nothing
remst1: push ax
push bx
push cx
push dx
push si
mov si,listptr
mov ax,dirlist[si] ; Director table entry
and ax,not(strng+verb) ; clear type bits, leave string's pointer
mov dirlist[si],0 ; clear Director table entry
shl ax,1 ; index words not bytes
mov si,offset sptable ; list of string offsets in stbuf
add si,ax ; plus index = current slot
mov bx,[si] ; get offset of string to be deleted
mov dx,bx ; save in dx for later
mov cl,byte ptr [bx] ; get length byte
xor ch,ch ; get length of subject string
inc cx ; length byte too, cx has whole length
sub strmax,cx ; count space to be freed (adj end-of-buf ptr)
mov word ptr [si],0 ; clear sptable of subject string address
push cx ; save length of purged string
push di ; save di
push si
push es ; save es
push ds
pop es ; setup es:di to be ds:offset of string
mov di,dx ; destination = start address of purged string
mov si,dx ; source = start address of purged string
add si,cx ; plus string length of purged string.
mov cx,offset stbuf+stbuflen ; 1 + address of buffer end
sub cx,si ; 1 + number of bytes to move
dec cx ; number of bytes to move
jcxz remst2 ; z = none
cld ; direction is forward
rep movsb ; move down preserved strings
remst2: pop es ; restore regs
pop di
pop si
pop ax ; recover length of purged string (was in cx)
mov bx,offset sptable ; string pointer table
mov cx,maxstng ; max mumber of entries
remst4: cmp [bx],dx ; does this entry occur before purged string?
jbe remst5 ; be = before or equal, so leave it alone
sub [bx],ax ; recompute address (remove old string space)
remst5: add bx,2 ; look at next list entry
loop remst4 ; do all entries in sptable
pop si
pop dx
pop cx
pop bx
pop ax
ret
remstr endp
shkfre proc near ; show free key & string defs & space
push ax ; preserves all registers.
push bx
push cx
push dx
push kbtemp
mov dx,offset fremsg
mov ah,prstr
int dos
mov ax,maxkeys ; max number of key defs
sub ax,nkeys ; number currently used
call decout ; show the value
mov ah,prstr
mov dx,offset kyfrdef ; give key defs msg
int dos
mov bx,offset sptable ; table of string pointers
mov cx,maxstng ; number of pointers
mov kbtemp,0 ; number free
shkfr1: cmp word ptr [bx],0 ; slot empty?
jne shkfr2 ; ne = no
inc kbtemp ; count free defs
shkfr2: add bx,2 ; look at next slot
loop shkfr1 ; do all of them
mov ax,kbtemp ; number of free defs
call decout ; display
mov dx,offset stfrdef ; say free string defs
mov ah,prstr
int dos
mov ax,offset stbuf+stbuflen ; 1 + last byte in stbuf
sub ax,strmax ; offset of last free byte in stbuf
call decout
mov dx,offset stfrspc ; give free space part of msg
mov ah,prstr
int dos
pop kbtemp
pop dx
pop cx
pop bx
pop ax
ret
shkfre endp
; Initialize the keyboard tables at Kermit startup time. Optional procedure.
; Requires kbdinlst to be configured with mkeyw macro in the form
; mkeyw 'definition',keytype*256+keycode
; keytype is 0 for scan codes and non-zero for ascii.
; Returns normally.
kbdinit proc near ; read keyword kbdinlst and setup
push ds ; initial keyboard assignments.
pop es ; set es:di to datas segment
inc taklev ; pretend that we are in Take file
mov si,offset kbdinlst ; start of list of definitions
kbdini1:mov cl,byte ptr [si] ; cnt field (keyword length of macro)
xor ch,ch
jcxz kbdinix ; z = null cnt field = end of list
inc si ; look at text field
mov di,offset tranbuf ; where defkey expects text
cld
rep movsb ; copy cx chars to tranbuf
mov byte ptr [di],0 ; insert null terminator
inc si ; skip '$' field
mov ax,word ptr [si] ; get value field
mov keycode,ax ; set key ident value
push si
call dfkey2 ; put dfkey to work
nop
nop
nop
pop si
add si,2 ; point to next entry
jmp kbdini1 ; keep working
kbdinix:dec taklev ; reset Take file level
ret
kbdinit endp
;;; End of System Independent Procedures
;;; Begin System Dependent Procedures
; Read keyboard. System dependent.
; Return carry set if nothing at keyboard.
; If char present return carry clear with key's code in Keycode.
; If key is ascii put that in the low byte of Keycode and clear bit Scan in
; the high byte; otherwise, put the scan code in the lower byte and set bit
; Scan in the high byte.
; Bit Scan is set if key is not an ascii code.
; Two methods are used: Bios reading for Set Key ON, and DOS reading for
; Set Key OFF. DOS scan codes are coerced to Bios values as much as possible.
; Modifies register ax.
getkey proc near
mov keycode,0 ; clear old keycode
cmp dosflg,0 ; do DOS keyboard reading?
jne getky5 ; ne = yes, DOS
jmp getky6 ; do full Bios form
; ;;;;;;;; D O S ;;;;;;;;;;
getky5: mov dl,0ffh ; DOS read operation
mov ah,dconio ; from stdin
int dos
jnz getky5a ; nz = char available
stc ; carry set = nothing available
ret ; exit on no char
getky5a:cmp al,0 ; scan code precursor?
je getky5d ; e = yes
cmp al,16 ; Control P?
jne getky5b ; ne = no
mov al,114 ; force Control PrtSc scan code
jmp short getky5e ; process as scan code
getky5b:cmp al,BS ; backspace key?
jne getky5c ; ne = no
mov al,14 ; force scan code for BS key
jmp short getky5e ; process as scan code
getky5c:mov byte ptr keycode,al ; save ascii char
clc ; say have an ascii keycode
ret ; and exit
getky5d:mov dl,0ffh ; read second byte (actual scan code)
mov ah,dconio ; read via DOS
int dos
jnz getky5e ; nz = got a char
stc ; none, declare bad read
ret
; Check and modify to Bios scan codes
getky5e:mov byte ptr keycode,al ; save char code
cmp al,1 ; Alt escape
je getkya ; set Alt bit
cmp al,16 ; back tab
jb getky5g ; these remain unchanged
cmp al,50 ; start of meta keys
jb getkya ; b = set Alt bit
cmp al,84 ; Shift F1
jb getky5g ; b = no change
cmp al,94 ; Control F1
jb getkys ; set Shift bit
cmp al,104 ; Alt F1
jb getkyc ; set Control bit
cmp al,114 ; Control PrtSc
jb getkya ; set Alt bit
cmp al,120 ; Alt top rank
jb getkyc ; set Control bit
cmp al,132 ; Control PgUp
jb getkya ; set Alt bit
je getkyc ; set Control bit
cmp al,135 ; Shift F11, for Enhanced keyboard
jb getky5g ; no change
cmp al,137 ; Control F11
jb getkys ; set Shift bit
cmp al,139 ; Alt F11
jb getky5c ; set Control bit
cmp al,141 ; Control Up
jb getkya ; set Alt bit
cmp al,151 ; Alt Home
jb getkyc ; set Control bit
jmp short getkya ; set Alt bit
getkyc: or keycode,control ; set Control bit
jmp short getky5g
getkys: or keycode,shift ; set Shift bit
jmp short getky5g
getkya: or keycode,alt ; set Alt bit
getky5g:or keycode,scan ; ensure scan bit is set
clc ; report we have a scan keycode
ret ; and exit
; ;;;;;;;;;; B I O S ;;;;;;;;;;;;;
getky6: ; full BIOS keyboard reading
mov kbtemp,0001h ; low byte = status, high = read char
mov ah,byte ptr kbtemp ; anything at keyboard?
int kbint ; Bios keyboard interrupt
jnz getky1 ; nz = char available
stc ; carry set = nothing available
jmp short getkyx ; exit on no char available
getky1: mov ah,byte ptr kbtemp+1 ; read, no echo, wait til done
int kbint ; ==> ah = scan code, al = char value
or ax,ax ; Both bytes null for Control-Break?
jnz getky1a ; nz = no
push ax ; clear DOS buffer of Control-C by
mov ah,coninq ; doing DOS level read operation
int dos
pop ax ; restore reg
getky1a:
getky1c:push cx
mov cx,aliaslen ; number of aliased keys
or cx,cx
pop cx
jz getky2 ; z = none
push di ; check key (ax) for aliases
push cx
push es
push ds
pop es ; make es:di refer to datas segment
mov di,offset aliaskey ; list of aliased keys
mov cx,aliaslen ; number of entries
cld
repne scasw ; look for a match
pop es
pop cx
pop di
jne getky2 ; ne = not there
mov al,0 ; force use of scan code (in ah)
getky2: or al,al ; scan code being returned?
jnz getky3 ; nz = no
mov byte ptr keycode,ah ; store scan code for gsh
push ax
push bx
call gsh ; get modified shift state
or byte ptr keycode+1,al ; store in type field of keycode
pop bx
pop ax
xchg ah,al ; put scan code in al
or keycode,scan ; set scan flag (vs ascii)
getky3: mov byte ptr keycode,al ; return key's code (usually ascii)
clc ; carry clear = got a char
getkyx: ret
getkey endp
; get shift state into al. We care about only shift, ctl, and alt keys.
; right shift is collapsed into left shift. NumLock offsets Shift on keypad
; white keys.
gsh proc near
xor ah,ah ; [jhw]
ret
gsh endp
; Do any local processing after reading a key during active translation
; Avoids same actions if a key is being defined or shown.
postkey proc near
; Key Click code for VT102 emulator
cmp flags.vtflg,0 ; emulating? (0 = no)
je postke1 ; e = extra clicks not available
test vtemu.vtflgst,vskeyclick ; flags from SET TERM
jz postke1 ; z = extra clicks not wanted
call vclick ; click, what else?
postke1:ret
postkey endp
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end