home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msvp98b1.lzh
/
MSUP98.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-12-06
|
91KB
|
2,247 lines
NAME msup98
; File MSUP98.ASM
; Keyboard translator for NEC PC-9801 by Hirofumi Fujii (KEK)
;
; 17-Apr-1991 Many modifications have been done by Joe Doupnik.
; 13-Aug-1990 the input for external procedure PROMPT has been changed
; It accepts ASCIIZ string. The 'dsafkdf' string has been
; chagned to ASCIIZ for this purpose.
;
; 10-Dec-1988
; To use CTRL+SPACE, ROLL-UP, ROLL-DOWN etc., I introduced new scan codes.
; These scan codes are private, NOT the NEC codes. Therefore you must be
; careful for new models.
;
; Normal +SHIFT +CTRL
; SPACE 34h A4h B4h
; ROLL-UP 36h A6h B6h
; ROLL-DOWN 37h A7h B7h
; INS 38h A8h B8h
; DEL 39h A9h B9h
; up arrow 3Ah AAh BAh
; left arrow 3Bh ABh BBh
; right arrow 3Ch ACh BCh
; down arrow 3Dh ADh BDh
; HOME CLR 3Eh AEh ---
; HELP 3Fh AFh BFh
;
; Getkey has three modes, BIOS mode, CON mode and DOS mode. In the BIOS mode,
; keys are read by using NEC keyboard bios (int 18h). The scan code of
; the key can be read as well as JIS-Roman code. This method is quite safe
; for terminal emulation unless Japanese front end processor is used.
; In the CON mode, keys are read by using MS-DOS function call (int 21h).
; In this mode, the scan code of the key cannot be read. Function keys,
; ROLL-UP, ROLL-DOWN, INS, DEL, arrow keys, HOME-CLR and HELP keys are
; programable, so that they can be programmed to return its scan code.
; However, numeric keys, minus, star, plus, equal, comma, period keys
; in the keypad are not programmed. They cannot be distinguished from
; the nomal keys. Therefore, a dangerous method is employed in this
; program to read the keypad keys. If you feel something wrong at keypad
; keys, ESC, TAB or BS key, try to use in BIOS mode.
;
; Last edit 23 Oct 1988
; 23 Oct 1988 Special treatment for CTRL-@ (NUL).
; 30 Aug 1988 Keypad keys can be read in CON mode.
; 16 Jul 1988 all the Kanji features went to MSXP98.ASM
; Keyboard translator, by Joe R. Doupnik, Dec 1986
; with contributions from David L. Knoell.
; For Generic keyboard reading (via DOS)
; edit history:
; Last edit 1 Jan 1988
; 1 Jan 1988 version 2.30
include mssdef.h
include msxp98.h
public keybd, dfkey, shkey, msuinit
public ans_keystr
public kbdlini, kbdlend
KEYCLICK_BIT equ 4
; NEC PC-9801 key related bios functions
read_key equ 0
sense_key equ 1
sense_shift equ 2
; sense_shift returns shift key state in AL
; b5 b4 b3 b2 b1 b0
; -+----+----+----+----+----+-----+
; |****|CTRL|GRPH|KANA|CAPS|SHIFT|
; -+----+----+----+----+----+-----+
; NEC PC-9801 STOP and COPY key interrupt numbers
INTNUM_COPY equ 5
INTNUM_STOP equ 6
; some definitions
maxkeys equ 256 ; maximum number of key definitions
maxstng equ 128 ; maximum number of multi-char strings
stbuflen equ 1024 ; 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
data segment
extrn taklev:byte, comand:byte, flags:byte
extrn shkadr:word, stkadr:word, trans:byte, ttyact:byte
; system dependent references
extrn vt100_flags:byte ; in MSXP98
extrn keyin_dos:byte ; in MSXP98
extrn vtmacname:word, vtmaclen:word ; external macro
;;; 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.$'
dfaskky db cr,lf,' Push key to be defined: $'
dfaskdf db ' Enter new definition: ',0
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,'$'
dfkoops 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$'
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 0 ; item number for keylist and dirlist
nkeys dw 0 ; number of actively defined keys
keycode dw 0 ; ascii/scan code for key
kbtemp dw 0 ; scratch storage for translator
brace db 0 ; brace detected flag byte
oldform db 0 ; old form Set Key, if non-zero
verblen dw 0 ; length of user's verb (work temp)
kwcnt dw 0 ; number of keywords (work temp)
msutake db 0 ; if being run from take file or not
twelve dw 12d
stringcnt dw 0 ; qty of string chars to be processed
stringptr dw 0 ; address of next string char
dosflg db 0
;;; End System Independent Data Area
;;; System Dependent Data Area
; old interrupt vectors for COPY and STOP key
old_copy_ofs dw ?
old_copy_sgm dw ?
old_stop_ofs dw ?
old_stop_sgm dw ?
intrkey dw 0
;
intkey_tab dw 06000h ; STOP
dw 06100h ; COPY
dw 08000h ; Shift+STOP
dw 08100h ; Shift+COPY
dw 09000h ; Ctrl+STOP
dw 09100h ; Ctrl+COPY
;
; 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. VT320 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,' decFind, decInsert, decRemove, decSelect, decPrev,'
db ' decNext'
db cr,lf,' User Definable Keys decF6, ...decF14, decHelp,'
db ' decDO, decF17, ...decF20'
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, holdscrn, modeline, break,'
db ' lbreak, nethold,'
db cr,lf
db ' hangup, null (send one), terminalR, terminalS, DOS, help,'
db ' 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 001Bh ; ESC
dw 0E08h ; BS
dw 0F09h ; TAB
dw 402Dh
dw 412Fh
dw 4237h
dw 4338h
dw 4439h
dw 452Ah
dw 4634h
dw 4735h
dw 4836h
dw 492Bh
dw 4A31h
dw 4B32h
dw 4C33h
dw 4D3Dh
dw 4E30h
dw 4F2Ch
dw 502Eh
dw 0A420h ; SHIFT+space
dw 0B420h ; CTRL+space
aliaslen equ ($-aliaskey) shr 1 ; number of words in aliaskey table
kverbs db 66 ; number of table entries below
mkeyw 'uparr',uparrw ; independent of ordering and case!
mkeyw 'dnarr',dnarrw ; mkeyw 'name',procedure entry point
mkeyw 'lfarr',lfarrw
mkeyw 'rtarr',rtarrw
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',kpmins
mkeyw 'kpcoma',kpcoma
mkeyw 'kpenter',kpentr
mkeyw 'kpdot',kpdot
mkeyw 'decF6',decf6
mkeyw 'decF7',decf7
mkeyw 'decF8',decf8
mkeyw 'decF9',decf9
mkeyw 'decF10',decf10
mkeyw 'decF11',decf11
mkeyw 'decF12',decf12
mkeyw 'decF13',decf13
mkeyw 'decF14',decf14
mkeyw 'decHelp',dechelp
mkeyw 'decDo',decdo
mkeyw 'decF17',decf17
mkeyw 'decF18',decf18
mkeyw 'decF19',decf19
mkeyw 'decF20',decf20
mkeyw 'decFind',decfind
mkeyw 'decInsert',decinsert
mkeyw 'decRemove',decremove
mkeyw 'decSelect',decselect
mkeyw 'decPrev',decprev
mkeyw 'decNext',decnext
mkeyw 'termtype',vtchg
mkeyw 'reset',vtreset
mkeyw 'prtscn',prtscn
mkeyw 'trnprs',trnprs
mkeyw 'modeline',trnmod
mkeyw 'break',sendbr
mkeyw 'hangup',chang
mkeyw 'null',snull
mkeyw 'help',cquery
mkeyw 'status',cstatus
mkeyw 'exit',cquit
mkeyw 'terminalR',vtrmac
mkeyw 'terminalS',vtsmac
mkeyw 'DOS',kdos
mkeyw 'logoff',klogof
mkeyw 'logon',klogon
mkeyw 'upone',upone
mkeyw 'dnone',dnone
mkeyw 'upscn',upscn
mkeyw 'dnscn',dnscn
mkeyw 'gupone',gupone
mkeyw 'gdnone',gdnone
; Initialization data.
kbdinlst equ this byte ; Kermit PC98 initialization time keyboard setup
mkeyw '\x1b',256 ; ESC key sends ESC
mkeyw '\x7f',270 ; BS key sends delete
mkeyw '\9',271 ; TAB key sends TAB
mkeyw '\8',313 ; DEL key sends backspace
mkeyw '\kuparr',314 ; Up arrow key
mkeyw '\klfarr',315 ; Left arrow key
mkeyw '\krtarr',316 ; Right arrow key
mkeyw '\kdnarr',317 ; Down arrow key send <ESC>[B
mkeyw '\kpf1',318 ; HOME/CLR
mkeyw '\kpf2',319 ; HELP
mkeyw '\kpf3',320 ; keypad minus
mkeyw '\kpf4',321 ; keypad slash
mkeyw '\kkp7',322 ; keypad 7
mkeyw '\kkp8',323 ; keypad 8
mkeyw '\kkp9',324 ; keypad 9
mkeyw '\kkpminus',325 ; keypad *
mkeyw '\kkp4',326 ; keypad 4
mkeyw '\kkp5',327 ; keypad 5
mkeyw '\kkp6',328 ; keypad 6
mkeyw '\kkpcoma',329 ; keypad +
mkeyw '\kkp1',330 ; keypad 1
mkeyw '\kkp2',331 ; keypad 2
mkeyw '\kkp3',332 ; keypad 3
mkeyw '\kkpenter',333 ; keypad =
mkeyw '\kkp0',334 ; keypad 0
mkeyw '\kkp0',335 ; keypad ,
mkeyw '\kkpdot',336 ; keypad .
mkeyw '\kdnone',310 ; ROLL UP
mkeyw '\kupone',311 ; ROLL DOWN
mkeyw '\kexit',352 ; STOP
mkeyw '\kprtscn',353 ; COPY
mkeyw '\kbreak',384 ; shift+STOP
mkeyw '\ktrnprs',385 ; shift+COPY
mkeyw '\x20',420 ; shift+SPACE
mkeyw '\knull',436 ; ctrl+SPACE
mkeyw '\kdnscn',438 ; ctrl+ROLL UP
mkeyw '\kupscn',439 ; ctrl+ROLL DOWN
mkeyw '\x1b$B',KI_CODE ; KI virtual key
mkeyw '\x1b(J',KO_CODE ; KO virtual key
dw 0 ; end of table marker
keypadnum dw 452Ah ; *
dw 492Bh ; +
dw 4F2Ch ; ,
dw 402Dh ; -
dw 502Eh ; .
dw 412Fh ; /
dw 4E30h ; 0
dw 4A31h ; 1
dw 4B32h ; 2
dw 4C33h ; 3
dw 4634h ; 4
dw 4735h ; 5
dw 4836h ; 6
dw 4237h ; 7
dw 4338h ; 8
dw 4439h ; 9
dw 273Ah
dw 263Bh
dw 302Ch
dw 4D3Dh ; =
keypadgrp dw 2008h ; *
dw 0209h ; +
dw 8009h ; ,
dw 0108h ; -
dw 010Ah ; .
dw 0208h ; /
dw 4009h ; 0
dw 0409h ; 1
dw 0809h ; 2
dw 1009h ; 3
dw 4008h ; 4
dw 8008h ; 5
dw 0109h ; 6
dw 0408h ; 7
dw 0808h ; 8
dw 1008h ; 9
dw 000Ah
dw 000Ah
dw 000Ah
dw 2009h ; =
kbcodes dw 80h ; keyboard read codes, 80h=not inited
data 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
; system independent external items
extrn comnd:near, prompt:near ; in msscmd
extrn strlen:near, prtscr:near ; in mssfil
extrn cnvlin:near, katoi:near, decout:near ; in msster
; system dependent external items
; these are system dependent action verbs, in msxgen
extrn beep:near, trnprs:near, sendbr:near
extrn chrout:near, cstatus:near, cquit:near, cquery:near
extrn klogon:near, klogof:near, kdos:near, snull:near, chang:near
extrn trnmod:near
extrn pf1:near, pf2:near, pf3:near, pf4:near
extrn kp0:near, kp1:near, kp2:near, kp3:near, kp4:near
extrn kp5:near, kp6:near, kp7:near, kp8:near, kp9:near
extrn kpmins:near, kpcoma:near, kpentr:near, kpdot:near
extrn uparrw:near, dnarrw:near, lfarrw:near, rtarrw:near
extrn decf6:near, decf7:near, decf8:near, decf9:near, decf10:near
extrn decf11:near, decf12:near, decf13:near, decf14:near
extrn dechelp:near, decdo:near
extrn decf17:near, decf18:near, decf19:near, decf20:near
extrn decfind:near, decinsert:near, decremove:near, decselect:near
extrn decprev:near, decnext:near
extrn keyinchg:near
extrn vtchg:near, vtreset:near
extrn upone:near, dnone:near, upscn:near, dnscn:near
extrn gupone:near, gdnone:near
extrn prtscn:near
extrn vtrmac:near, vtsmac:near, extmacro:near
extrn s2jis:near, is_kanji1:near
assume cs:code, ds:data, es:data
; 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
mov ttyact,1 ; doing single char output
cmp stringcnt,0 ; any leftover string chars?
je keybd0 ; e = no
jmp keyst2 ; yes, finish string
keybd0: 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 data 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 xltkey ; do character set translation
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 ax,[bx] ; cnt value
add ax,4 ; skip text and value word
add bx,ax ; look at next slot
loop keyvb1 ; walk to correct slot
sub bx,2 ; backup to value field
pop cx ; restore reg
mov bx,[bx] ; get value field of this slot
or bx,bx ; jump address defined?
jz keybdx ; z = 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
xor cx,cx ; init string length to null
or si,si ; is there a string pointer present?
jz keyst1 ; z = no, skip operation
cld ; scan forward
mov cx,[si] ; get string length
add si,2
keyst1: mov stringcnt,cx
mov stringptr,si
pop si
jcxz keybdx ; z = null length
keyst2: push si
mov si,stringptr ; pointer to next string char
cld
lodsb ; get new string char into al
pop si
dec stringcnt ; string chars remaining
inc stringptr
call keysv ; scan for embedded verbs
jc keyst4 ; c = not found, al has string char
jmp bx ; perform the verb (bx = address)
keyst4: call xltkey ; do character set translation
cmp stringcnt,0 ; last character?
je keyst5 ; e = yes, stop grouping for nets
mov ttyact,0 ; group output for networks
keyst5: jmp chrout ; send out the char in al
keybdx: clc ; return success (nothing to do)
ret
KEYBD ENDP
; Scan for keyboard verbs embedded in outgoing string. If found update
; string pointer and count to just beyond the verb and return action routine
; address in bx with carry clear. If failure return carry set and no change.
; Can invoke external procedure EXTMACRO if the verb is not known here.
keysv proc near
push ax
push si
push di
cmp al,'\' ; escape?
jne keysv7 ; ne = no
mov cx,stringcnt ; chars remaining
mov si,stringptr ; address of next char to read
mov brace,0 ; assume not using braces
cmp byte ptr [si],braceop ; starts with \{?
jne keysv1 ; ne = no
inc si ; skip the opening brace
dec cx
mov brace,bracecl ; expect closing brace
keysv1: cmp byte ptr [si],'K' ; starts with \{K or \K?
je keysv2 ; e = yes
cmp byte ptr [si],'k' ; starts as \{k or \k?
jne keysv7 ; ne = no, then it's a string
keysv2: inc si ; yes, skip the K too
dec cx
mov di,offset tranbuf ; copy verb name to this work buffer
xor ax,ax
mov [di],ax ; init the buffer to empty
keysv3: cld
jcxz keysv4 ; z = no more string chars
lodsb ; scan til closing brace or w/s or end
dec cx
cmp al,brace ; closing brace?
je keysv4 ; e = yes
cmp al,spc ; white space or control char?
jbe keysv3 ; be = yes
mov [di],ax ; copy to tranbuf and terminate
inc di
jmp short keysv3
keysv4: push si ; save input reading position
mov si,offset tranbuf ; where verb starts (needs si)
call tstkeyw ; find keyword, bx = action routine
pop si
jnc keysv4a ; nc = found the verb
call keysv8 ; invoke EXTMACRO worker for unknown
jc keysv7 ; carry = no verb to operate upon
keysv4a:cmp brace,0 ; need to end on a brace?
je keysv6 ; e = no
dec si ; break position
inc cx
cld
keysv5: jcxz keysv6 ; z = no more string characters
lodsb ; read string char
dec cx
cmp al,brace ; the brace?
jne keysv5 ; ne = no, repeat until it is found
keysv6: mov stringptr,si ; where we finished+1
mov stringcnt,cx ; new count of remaining chars
pop di
pop si ; original si, starting place
pop ax ; original ax
clc
ret
keysv7: pop di ; verb not found
pop si
pop ax
stc
ret
; Worker. Unknown verb name as string {\kverb} or {\k{verb}}. Use EXTMACRO
; procedure (in msyibm typically), point to verb name with vtmacname, length
; of it in byte vtmaclen, address of EXTMACRO to BX. Upper case the verb.
; Enter with tranbuf holding the verb, asciiz, without \K and braces.
; Returns BX set to EXTMACRO proc, vtmacname pointing to verb (uppercased)
; and vtmaclen holding the length of verb.
keysv8: mov bx,offset extmacro ; use this external macro pointer
mov vtmacname,offset tranbuf; select extmacro procedure address
mov dx,offset tranbuf ; point to name for extmacro
push cx
call strlen ; get its length
mov vtmaclen,cx ; length for extmacro
jcxz keysv11 ; z = none
push si ; convert verb name to upper case
mov si,dx ; verb, without leading \K stuff
cld
keysv9: lodsb ; read a name byte
cmp al,'a' ; before lower case?
jb keysv10 ; e = yes
cmp al,'z' ; above lower case?
ja keysv10 ; a = yes
and al,not 20h ; convert to upper case
mov [si-1],al ; put it back
keysv10:loop keysv9 ; do all bytes, asciiz
pop si
pop cx
clc ; carry clear = ready to execute
ret
keysv11:stc ; carry set = no verb, do nothing
pop cx
ret
keysv endp
; SET KEY - define a key (procedure dfkey)
; SET KEY <key ident><whitespace><new meaning>
; Call from Kermit level. Returns carry set if failure.
;
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
or byte ptr kbcodes,80h ; say kbcodes not-initiated
mov dx,offset tranbuf ; our work space
mov word ptr tranbuf,0 ; insert terminator
mov bx,offset dfhelp1 ; first help message
mov ah,cmword ; parse a word
call comnd ; get key code or original ascii char
mov cl,taklev ; reading from Take file
mov msutake,cl ; save here
or ax,ax ; any text given?
jnz dfkey12 ; nz = yes, so don't consider prompts
; interactive key request
cmp taklev,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 dfkey15 ; e = yes, reinit keyboard [2.31]
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 dfkey13 ; e = yes, use standard kbd calls
; IBM cmp dx,'kl' ; first two letters of "lk" (LK250)?
; IBM je dfkey13 ; e = yes
cmp ax,1 ; number of characters received
jbe dfkey12a ; be = stay here
jmp dfkey1 ; a = more than one, decode
dfkey12a:mov ah,byte ptr tranbuf ; get the single char
mov byte ptr keycode,ah ; store as ascii keycode
jmp dfkey1b ; go get definition
dfkey13:push dx ; save command letters
mov ah,cmeol ; get end of line confirmation
call comnd
pop dx
jnc dfkey14 ; nc = success
ret
dfkey14:mov al,0ffh ; set DOS keyboard read flag
cmp dx,'fo' ; first two letters of "off"
je dfkey14a ; e = yes, use DOS keyboard calls
xor al,al ; clear DOS keyboard read flag
cmp dx,'no' ; first two letters of "on"
je dfkey14a ; e = yes, use standard kbd calls
mov ah,dosflg ; get current flag
mov dosflg,1 ; engage for chk250 test
;ibm push ax
;ibm call chk250 ; see if LK250 driver is present
;ibm pop ax
;ibm mov al,ah ; recover current setting
;ibm cmp got250,0 ; did we find the driver?
;ibm je dfkey14a ; e = no
;ibm call kbrest ; and activiate it if so
mov al,1 ; say LK250
dfkey14a:mov dosflg,al ; store new keyboard flag
ret
dfkey15:mov ah,cmeol
call comnd ; confirm request before proceeding
jnc dfkeyc ; nc = success
ret ; failure
;;jpn cmp dx,'ik' ; KI:Kanji-in virtual key? [HF01]
;;jpn jne dfkey14 ; ne = no. [HF01]
;;jpn mov keycode,KI_code ; store keycode [HF01]
;;jpn jmp dfkey1b ; go get definition [HF01]
;;jpndfkey14:
;;jpn cmp dx,'ok' ; KO:Kanji-out virtual key? [HF01]
;;jpn jne dfkey14a ; ne = no. [HF01]
;;jpn mov keycode,KO_code ; store keycode [HF01]
;;jpn jmp dfkey1b ; go get definition [HF01]
;;jpndfkey14a:
;;jpn cmp ah,1 ; number of characters received
;;jpn ja dfkey1 ; a = more than one, decode
;;jpn mov ah,byte ptr tranbuf ; get the single char
;;jpn mov byte ptr keycode,ah ; store as ascii keycode
;;jpn jmp dfkey1b ; go get definition
dfkey0: mov dx,offset dfhelp1 ; say bad definition command
mov ah,prstr
int dos
stc ; failure
ret
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 data segment
xor ax,ax ; null, value to be stored
mov di,offset dirlist ; director table
cld
rep stosw ; clear it
mov cx,maxkeys ; size of keycode tables
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
clc ; success
ret
; 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 data 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,cmline ; read rest of line into tranbuf
call comnd ; allow null definitions
or ax,ax ; 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
mov comand.cmwhite,1 ; allow leading whitespace
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,cmline ; read rest of line into tranbuf
call comnd
jc dfkey1x ; exit now on ^C from user
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
dfkey1x:ret ; failure exit
dfkey1g:push ax ; save count
mov ah,cmeol ; get a confirm
call comnd
pop cx ; string length
jc dfkey1x ; none so declare parse error
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 dfkoops ; Oops! msg
mov ah,prstr ; complain and don't redefine
int dos
stc ; failure
ret
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
stc ; failure
ret
; 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
or al,al ; premature end?
jz dfkey4b ; z = 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
stc ; failure
ret
; 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
stc ; failure
ret
; 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 data 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
or ah,ah
jz dfkey7a ; z = 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:clc ; return success
ret
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
mov ah,cmeol ; get a confirm
call comnd ; ignore any additional text
push bx
mov dx,offset shkmsg1 ; ask for original key
mov ah,prstr
int dos
or byte ptr kbcodes,80h ; say kbcodes not-initiated
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: mov ah,0bh ; check console, check ^C
int dos
cmp flags.cxzflg,'C' ; a ^C?
je shky1b ; e = yes, quit
or al,al
jz shky1a ; z = nothing
call getkey ; get any key
jc shky1a ; c = nothing at keyboard yet, wait
shky1b: pop cx ; resume loop
cmp flags.cxzflg,'C' ; a ^C?
je shky1c ; e = yes, quit
loop shky1
shky1c: 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 data 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
xor cx,cx ; current slot number
shkey6b:cmp cx,dx ; this slot?
je shkey6c ; e = yes, print the text part
ja shkeyx ; a = beyond, exit bad
mov ax,[bx] ; get cnt (keyword length)
add ax,4 ; skip count and two byte value
add bx,ax ; bx = start of next keyword slot
inc cx ; current keyword number
jmp short shkey6b ; try another
shkey6c:push cx
mov cx,[bx] ; length of definition
add bx,2 ; look at text field
mov di,bx ; offset for printing
call prtscr ; print counted string
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
call prtscr ; print counted string, again
pop cx
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 cx,word ptr [si] ; get string length
add si,2 ; 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
clc ; return success
ret
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: dw cnt (length of string 'word')
; db 'word' (keyword string)
; 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 [bx],cx ; compare length vs table keyword
jne tstkw4 ; ne = not equal lengths, try another
push si ; lengths match, how about spelling?
push bx
add bx,2 ; 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 ax,[bx] ; cnt (keyword length from macro)
add ax,4 ; skip over count and two byte value
add bx,ax ; bx = start of next keyword slot
jmp tstkw3 ; do another comparison
tstkw5: ; get action pointer
mov ax,[bx] ; cnt (keyword length from macro)
add ax,2 ; skip over count
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 data segment
cld
mov [di],cx ; length of text for new string
add di,2 ; 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 cx,[bx] ; get length of subject string
add cx,2 ; length word 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
or byte ptr kbcodes,80h ; say kbcodes not-initiated
push ds ; initial keyboard assignments.
pop es ; set es:di to data segment
inc taklev ; pretend that we are in Take file
;ibm call chk250 ;** LK250 support begin
;ibm cmp got250,1 ;** is it installed?
;ibm jne kbdini0 ;** ne = no
;ibm call kbrest ;** else initialize to DEC mode
;ibm mov si,offset kb250lst ;** load extensions
;ibm jmp short kbdini1 ;** LK250 support end
kbdini0:mov si,offset kbdinlst ; start of list of definitions
kbdini1:mov cx,[si] ; cnt field (keyword length of macro)
jcxz kbdinix ; z = null cnt field = end of list
add si,2 ; 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
mov ax,word ptr [si] ; get value field
mov keycode,ax ; set key ident value
push si
call dfkey2 ; put dfkey to work
pop si
add si,2 ; point to next entry
jmp kbdini1 ; keep working
kbdinix:dec taklev ; reset Take file level
;ibm call udkclear ; clear User Definable Keys
;ibm mov cx,40h ; segment 40h
;ibm mov es,cx
;ibm mov cl,byte ptr es:[96h] ; kbd_flag_3, Enhanced keyboard area
;ibm test cl,10h ; select Enhanced kbd presence bit
;ibm jz kbdinx1 ; z = regular (88)
;ibm mov keyboard,101 ; 101 = enhanced kbd
kbdinx1:ret
kbdinit endp
;;; End of System Independent Procedures
;;; Begin System Dependent Procedures
ans_keystr proc near
; returns key definition strings.
; inputs:
; ax scan code for the key
; outputs:
; cx number of strings (may be zero)
; bx address of the string buffer
;
xor cx,cx ; clear counter
cmp nkeys,0
jg ans_keystr1
jmp ans_keystrex
ans_keystr1:
push di ; search keylist for this keycode
push cx ; save some registers
push es
mov di,offset keylist ; list of defined keycode words
mov cx,nkeys ; number of words to examine
push ds
pop es ; make es:di point to data segment
cld
repne scasw ; find keycode in list
pop es ; restore regs
pop cx
je ans_keystr2 ; e = found, work with present di
pop di ; restore original di
jmp ans_keystrex
ans_keystr2:
sub di,2 ; correct for auto increment
sub di,offset keylist ; subtract start of list ==> listptr
mov bx,offset dirlist ; get the director address
add bx,di
pop di ; restore original di
; dispatch on Director code
mov ax,[bx]
test ax,verb ; verb only?
jnz ans_keystrex ; nz = yes
test ax,strng ; multi-char string only?
jnz ans_keystr3 ; nz = yes, else single char & no xlat.
mov cx,1 ; do single CHAR output (char in al)
inc bx
jmp ans_keystrex
;
ans_keystr3:
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 bx,sptable[si] ; memory offset of selected string
pop si
cmp bx,0 ; is there a string pointer present?
je ans_keystrex ; e = no, skip operation
mov cx,[bx] ; get string length byte to cx [kaneko]
add bx,2 ; adjust pointer [kaneko]
;
ans_keystrex:
ret
ans_keystr endp
; 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.
; Modifies register ax.
getkey proc near
cmp intrkey,0 ; Interrupt key pressed ?
jne getkey01 ; ne = Yes.
jmp getkey00 ; go to normal process
getkey01:
push bx
mov ax,intrkey
dec ax ; index starts from 1
shl ax,1 ; item size in the table is 2 bytes
mov bx,offset intkey_tab ; set table
add bx,ax ; add index
mov ax,[bx] ; get keycode
mov intrkey,0 ; clear index
pop bx
jmp getkey1
getkey00:
mov keycode,0
cmp keyin_dos,0 ; Keyinput using BIOS ?
je getkey0 ; e = yes, BIOS key input
cmp keyin_dos,1 ; Keyinput using CON ?
jne getkey02 ; ne = no
jmp getkey_con
getkey02:
jmp getkey_dos
;
; Keyinput using BIOS
;
getkey0:
mov ah,sense_key
int bios
cmp bh,0
jne getky1 ; ne = char available
stc ; carry set = nothing available
jmp getkyx ; exit on no char available
getky1:
mov ah,read_key
int bios
cmp al,'^' ; check SHIFT+'^'
jne getky1_2
mov ah,sense_shift
int bios
test al,1
jz getky1_1
mov ax,0C60h ; Back quote
jmp getkey1
getky1_1:
mov ax,0C5Eh ; '^'
jmp getkey1
getky1_2:
cmp ah,34h
jb getkey1
cmp ah,3Fh
ja getkey1
push dx
mov dx,ax ; save code
mov ah,sense_shift ; sense shift key
int bios
test al,10h ; CTRL pressed ?
jz getky1_3 ; z = no
add dx,08000h
jmp getky1_4
getky1_3:
test al,1 ; SHIFT pressed ?
jz getky1_4 ; z = no
add dx,07000h
getky1_4:
xchg ax,dx
pop dx
getkey1:
push di ; check key (ax) for aliases
push cx
push es
mov di,offset aliaskey ; list of aliased keys
mov cx,aliaslen ; number of entries
jcxz getky2 ; z = no entries
push ds
pop es ; make es:di point to data segment
cld
repne scasw ; look for a match
jne getky2 ; ne = not there
mov al,0 ; force use of scan code (in ah)
getky2: pop es
pop cx
pop di
or al,al ; scan code being returned?
jnz getky3 ; nz = no
cmp ax,1A00h ; CTRL-@ key ?
je getky3
xchg ah,al ; put scan code in ident area
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
;
; Keyinput using MS-DOS console I/O + sense shift key
;
getkey_con:
push dx
mov ah,6 ; direct console I/O
mov dl,0FFh ; read
int dos
jnz getkey_con6
jmp getkey_con0
getkey_con6:
cmp al,0FFh ; special key ?
jne getkey_con61 ; ne = no
jmp getkey_conS
getkey_con61:
mov dx,ax
mov ah,sense_shift ; sense shift key
int bios
xchg ax,dx ; now ax=code, dx=shift_key
cmp al,3Dh ; is it '=' key ?
jne getkey_con4
jmp getkey_conK ; goto keypad-key check
getkey_con4:
cmp al,2Ah
jb getkey_con3
cmp al,39h
ja getkey_con3
jmp getkey_conK ; goto keypad-key check
getkey_con3: ; Normal key
mov ah,0
cmp al,'^'
jne getkey_con5
test dl,1 ; SHIFT pressed ?
jz getkey_con2 ; z = no
mov al,60h ; backquote
jmp getkey_con2
getkey_con5:
cmp al,20h
ja getkey_con2
cmp al,8 ; BS ?
jne getkey_con51 ; ne = No.
mov ah,22h ; assume CTRL + H
test dl,10h ; test CTRL key
jnz getkey_con2 ; nz = Pressed.
mov ah,0Eh ; BS key
jmp getkey_con2
getkey_con51:
cmp al,9 ; TAB ?
jne getkey_con52 ; ne = No.
mov ah,17h ; assume CTRL + I
test dl,10h ; test CTRL key
jnz getkey_con2 ; nz = Pressed.
mov ah,0Fh ; TAB key
jmp getkey_con2
getkey_con52:
cmp al,1Bh ; ESC ?
jne getkey_con53 ; ne = No.
mov ah,1Bh ; assume CTRL + [
test dl,10h ; test CTRL key
jnz getkey_con2 ; nz = Pressed.
mov ah,0 ; ESC key
jmp getkey_con2
getkey_con53:
cmp al,0 ; NUL ?
jne getkey_con54 ; ne = No.
mov ah,1Ah ; CTRL + @
jmp getkey_con2
getkey_con54:
cmp al,20h ; SPACE ?
jne getkey_con55 ; ne = No.
mov ah,34h ; set scan code
test dl,10h ; test CTRL key
jz getkey_con2 ; z = Not Pressed.
mov ax,0B420h ; CTRL-SPACE
getkey_con55:
getkey_con2:
pop dx
jmp getkey1
getkey_con0:
pop dx
stc
ret
;
getkey_conS:
mov ah,6
mov dl,0FFh
int dos
jnz getkey_conS1
jmp getkey_con0
getkey_conS1:
mov ah,al
xor al,al
cmp ah,34h
jb getkey_conS4
cmp ah,3Fh
ja getkey_conS4
push dx
mov dx,ax ; save code
mov ah,sense_shift ; sense shift key
int bios
test al,10h ; CTRL pressed ?
jz getkey_conS2 ; z = no
add dx,08000h
jmp getkey_conS3
getkey_conS2:
test al,1 ; SHIFT pressed ?
jz getkey_conS3 ; z = no
add dx,07000h
getkey_conS3:
xchg ax,dx
pop dx
getkey_conS4:
jmp getkey_con2
;
getkey_conK:
mov bx,offset keypadgrp
xor ah,ah
mov dx,ax
sub ax,2Ah
shl ax,1
add bx,ax
mov ax,[bx]
mov bx,ax
xor bl,bl
mov ah,04h
int BIOS
test ax,bx
jnz getkey_conK1
mov ax,dx
jmp getkey_con2
getkey_conK1:
mov ax,dx
mov bx,offset keypadnum
sub ax,2Ah
shl ax,1
add bx,ax
mov ax,[bx]
jmp getkey_con2
getkey_dos:
push dx
mov ah,6 ; direct console I/O
mov dl,0FFh ; read
int dos
jnz getkey_dos6
jmp getkey_dos0
getkey_dos6:
cmp al,0FFh ; special key ?
je getkey_dos1 ; e = yes
jmp getkey_dos2
getkey_dos1:
mov ah,6
mov dl,0FFh
int dos
jz getkey_dos0
mov ah,al
xor al,al
getkey_dos2:
pop dx
jmp getkey1
getkey_dos0:
pop dx
stc
ret
getkey endp
; Return modified char code, depending on SET TERM CHAR-SET and active
; Code Page. Enter and exit with char in AL.
xltkey proc near
ret
xltkey endp
postkey proc near ; do sys dep action after reading
test vt100_flags,KEYCLICK_BIT
je postkey_ex
push ax
push cx
;
mov al,06h
out 37h,al ; bell on
mov cx,1000h
postkey1:
loop postkey1
;
mov al,07h
out 37h,al ; bell off
;
pop cx
pop ax
postkey_ex:
ret ; key during active translation
postkey endp
; Interrupt routine for STOP and COPY keys
keyint_entry proc far
stop_int:
push ax
push ds
;
mov ax,data
mov ds,ax
cmp intrkey,0
jne keyint_entry3
mov intrkey,1
jmp keyint_entry1
;
copy_int:
push ax
push ds
;
mov ax,data
mov ds,ax
cmp intrkey,0
jne keyint_entry3
mov intrkey,2
;
keyint_entry1:
;
mov ah,sense_shift
int bios
test al,10h ; CTRL?
jz keyint_entry2
add intrkey,4
jmp keyint_entry3
keyint_entry2:
test al,1 ; SHIFT?
jz keyint_entry3
add intrkey,2
keyint_entry3:
;
pop ds
pop ax
iret
keyint_entry endp
; Keyboard local initialization routine
kbdlini proc near
pushf
cli ; disable interrupt
;
push ax
push bx
push dx
push es
;
mov intrkey,0
;
mov ah,35h ; read interrupt vector
mov al,INTNUM_COPY ; for COPY key interrupt
int DOS ; system call
mov old_copy_ofs,bx ; save vector
mov old_copy_sgm,es
;
mov ah,35h ; read interrupt vector
mov al,INTNUM_STOP ; for STOP key interrupt
int DOS ; system call
mov old_stop_ofs,bx ; save vector
mov old_stop_sgm,es
;
mov dx,offset copy_int
mov ax,cs
push ds
mov ds,ax
mov ah,25h
mov al,INTNUM_COPY
int DOS
pop ds
;
mov dx,offset stop_int
mov ax,cs
push ds
mov ds,ax
mov ah,25h
mov al,INTNUM_STOP
int DOS
pop ds
;
pop es
pop dx
pop bx
pop ax
;
popf
ret
kbdlini endp
; keyboard local end routine
kbdlend proc near
pushf
cli ; disable interrupt
;
push ax
push dx
;
mov dx,old_stop_ofs
mov ax,old_stop_sgm
push ds
mov ds,ax
mov ah,25h
mov al,INTNUM_STOP
int DOS
pop ds
;
mov dx,old_copy_ofs
mov ax,old_copy_sgm
push ds
mov ds,ax
mov ah,25h
mov al,INTNUM_COPY
int DOS
pop ds
;
pop dx
pop ax
popf
ret
kbdlend endp
code ends
end