📄 llcevt.asm
字号:
ADD DI,DX ;get byte offset in table
AND BYTE PTR[DI],0FDH ;disable the corr. key
; carry is cleared
DISBL2:
POP DX ;restore [DX]
RET ; with NC
SUBTTL B$KBDTRP - Keyboard interrupt / monitor loop
PAGE
;***
;B$KBDTRP
;
;PURPOSE:
; The keyboard interrupt handler first branches to
; this routine to see if any of the following keys
; were typed in that order:
; 1. The NUM_TKEYS trappable keys including the NUM_UKEYS user
; defined trap keys.
; 2. PRTSC key, LPT echo toggle key, Pause key
; or the Break key.
; If any of the above keys were hit, B$KBDTRP sets
; Event flag and the corresponding key flag and
; returns.
; If none of the above keys were hit then the
; routine branches to the ROM keyboard interrupt
; handler.
;
;ALGORITHM:
; if (key typed is the LPTECHO key) then
; begin
; set LPTFLG
; set EVTFLG and KEYFLG
; end
; If (key typed is a valid trap key for which
; trapping is enabled) then
; begin
; set the corr. TRAP key flag in the TRAPTABLE
; set the EVTFLG and KEYFLG
; end
; else
; if (key typed is PAUSE key and CTRL PAUSE
; trapping enabled) then
; begin
; set PAUSE key flag
; set EVTFLG and KEYFLG
; end
; else
; if (key typed is BREAK key and CTRL BREAK
; trapping enabled) then
; begin
; set BREAK key flag
; set EVTFLG and KEYFLG
; end
; else
; continue with ROM keyboard interrupt
; handler
;
;DATA STRUCTURE:
; This routine also uses the TRAP TABLE data
; structure described above in B$RDKYBD.
;
;ENTRY:
; None
;
;EXIT:
; Set the EVTFLG, KEYFLG and the corresponding key
; flag if any of the enabled trap keys were typed.
;
;MODIFIED:
; None
;
;***********************************************************************
dbpub B$KBDTRP
B$KBDTRP:
ENABLE ;enable further interrupts
PUSH AX
PUSH BX
PUSH CX
PUSH DS
PUSH DI
PUSH ES
XOR CX,CX
MOV DS,CX ;zero DS
MOV BX,KBDFLG ;set BX to special status flag's addr
MOV AH,BYTE PTR[BX] ;get the mask in AH
CALL B$GETDS
MOV DS,BX ;get the addr of basic data seg
MOV ES,BX ;make [ES] = [DS]
IN AL,KBDATA ;else get keyboard data in acc.
; when enter here,
; [AX]=[shift status|scan code]
MOV KEYHIT,AX ; store the key hit
CMP AL,ScanExt1 ; is extended scan code (E0H) ?
JZ SetExtFlg ; Brif yes
CMP AL,ScanExt2 ; is extended scan code (E1H) ?
JNZ SetToggle ; Brif not
SetExtFlg:
MOV WasE0E1,80H ; set extended scan code flag
JMP NONE ; let ROM handles it
SetToggle:
AND AH,6FH ;throw away INS & SCROLL (80H & 10H)
;and continue with the INT handler.
OR AH,WasE0E1 ; or the flag for extended key
MOV WasE0E1,0 ; reset extended scan code flag
TEST AH,3 ; was either right or left shift ?
JZ NO_SHFT ; Brif not
OR AH,3 ; make them the same
NO_SHFT:
TEST b$EventFlags,InSLEEP ; in sleep statement?
JZ NoWakeup ; brif not -- nothing to wake up
OR AL,AL ; BREAK scan code?
JS NoWakeup ; brif so -- don't wake up SLEEP
CALL B$Wakeup ; key hit -- force SLEEP statement wakeup
NoWakeup:
CALL CHKLPT ;check for CTRL PRTSC
CMP WASPOS,0 ;Pause active ?
JE NOPAUS ;Brif not
AND AL,07FH ;else strip bit 7
NOPAUS:
CALL B$CHKTRP ; check for trap keys
JC KBDRET ;Brif found
CALL OTHERS ;check for CTRL PAUSE and CTRL BRK
JC KBDRET ;Brif found
JMP NONE
KBDRET:
MOV KEYFLG,1 ;set flag for key event
CALL B$TrapEvent ;set global event flag
IN AL,KBDATA+1 ;get keyboard control port
MOV AH,AL ;save it in AH
OR AL,80H ;keyboard reset bit
PAUSE ;make sure instruction fetch has occurred
OUT KBDATA+1,AL ;Ack so keyboard can Int again
MOV AL,AH ;get control bits back
PAUSE ;make sure instruction fetch has occurred
OUT KBDATA+1,AL ;restore keyboard mode
MOV AL,EOI ;send End of Interrupt
PAUSE ;make sure instruction fetch has occurred
OUT INTA0,AL ;to 8259
STC ;carry since we processed char
ROMINT:
;CF indicates whether we processed
;character or not
POP ES
POP DI
POP DS
POP CX
POP BX
POP AX
JC REALRT
INT ROMKBD
REALRT:
IRET
SUBTTL
PAGE
;**
;This routine checks for CTRL PRTSC
;and if CTRL PRTSC is down it sets LPTFLG
;and the event flags
CHKLPT:
TEST AH,CTRLDown ; CTRL down ?
JZ LPTRET ;Brif not
CMP AL,ScanPrtsc ; was it the PRTSC key ?
JNE LPTRET ;Brif not
TEST PPBEBL,04H ;PRTSC key trapping enabled ?
JZ LPTRET ;Brif not
MOV LPTFLG,1 ;else set printer echo flag
MOV KEYFLG,1 ;set flag for key event
CALL B$TrapEvent ;set the global event flag
LPTRET:
RET
;**
;This routine checks for any of the
;NUM_TKEYS trappable keys and if found sets
;the trap flag for the corresponding key
dbpub B$CHKTRP
B$CHKTRP:
CMP KEYTRP,1 ;key trapping enabled ?
JNE NoTrap ;Brif not
; check F11/F12, or F1-F10 & cursor movement
; keys, and then user defined keys
XOR CX,CX ; CX=0, in case it is F11
CMP AL,ScanF11 ; is F11/F12
JB SetTbl1 ; Brif not
MOV BX,OFFSET DGROUP:TRTBL4 ; [BX]=offset of trap table 4
JZ IsTrapable ; Brif F11, TRAPPED need BX & CX
DEC CX ; CX=-1, TRAPPED need negative 0-relatived #
CMP AL,ScanF12 ; is F12 ?
JZ IsTrapable ; Brif yes, TRAPPED need BX & CX
JMP SHORT UsrKeys ; search user defined keys
SetTbl1:
TEST AH,80H ; is new set of cursor moving keys ?
JNZ UsrKeys ; Brif yes
MOV DI,OFFSET DGROUP:TRTBL1 ; [DI]=offset of trap table 1
MOV CX,OrgFky+CsrMovKy ; [CX]=count of keys
MOV BX,OFFSET DGROUP:TRTBL2 ; [BX]=offset of trap table 2
CLD ;just to be safe
REPNZ SCASB ;search for a trappable key
JNZ UsrKeys ; Brif none found
SUB CX,OrgFky+CsrMovKy-1 ; get negative 0-relative key
IsTrapable:
CALL TRAPPED ; trappable ?
JC SHORT TrpExit ; is a trapped key, return with CY
UsrKeys:
MOV DI,OFFSET DGROUP:USRTBL1;[DI]=offset of user trap_table 1
MOV CX,NUM_UKEYS ; [CX]=count of keys
MOV BX,OFFSET DGROUP:USRTBL2;[BX]=offset of user trap_table 2
CLD ; just to be safe
Loop2:
REPNZ SCASW ;search for a trappable key
JNZ NoTrap ; Brif none found
SUB CX,NUM_UKEYS-1 ; get the negative 0-relative key #
PUSH BX ; save BX for next run, BX is needed by
; TRAPPED and is ruined in it
CALL TRAPPED ; trappable ? on return CX=positive
; 0-relative key #, CY indicate the key is
; trapable, ZR or NC indicate not trapable
POP BX ; get BX back
JC TrpExit ; exit with carry set if found
SUB CX,NUM_UKEYS-1 ; get back count in [CX]
JCXZ NoTrap ; if zero, then done, no trap key found
NEG CX
JMP SHORT Loop2 ; look for other trappable keys
NoTrap:
CLC ;CLC to indicate none found
TrpExit: ; exit
RET
TRAPPED: ; this routine returns with
; CF set if the key is trappable
; else returns with Z flag set & NC
NEG CX ;number
ADD BX,CX ;get byte offset into table
TEST BYTE PTR[BX],TRP_VALID ; key valid?
JZ NOTFOUND ; Brif not -- return with carry clear
TEST BYTE PTR[BX],TRP_ENABLED ; key trapping enabled?
JZ NOTFOUND ; Brif not -- return with carry clear
OR BYTE PTR[BX],TRP_OCCURED ; else set the trap key flag
GotKeyBreak:
STC ;STC to indicate that a trappable
NOTFOUND:
RET ;key was found
;**
;This routine checks for CTRL PAUSE and CTRL BRK
;in that order and if found returns with carry set
;else returns with carry clear.
OTHERS:
TEST AH,CTRLDown ; CTRL down ? (carry reset NC)
JZ NOTFND ;Brif not
CMP AL,ScanPause ; was it CTRL PAUSE ?
JNE BRKCHK ;Brif not
TEST AH,ALTDown ; was ALT also down ?
JNZ OTHRET ;EAT CTRL ALT PAUSE
TEST PPBEBL,02H ;PAUSE key trapping enabled ?
JZ BRKCHK ;Brif not
CMP WASPOS,0 ;CTRL PAUSE active ?
JZ SETPOS ;Brif not (^S not active, so treat
;this as ^S)
JMP SHORT OTHRET ;else just eat the character
SETPOS:
MOV POSFLG,1 ;else set the PAUSE key flag
JMP SHORT OTHRET ;and return
BRKCHK:
CMP AL,ScanBreak ;was it CTRL BRK ?
JNE NOTFND ;Brif not
CMP b$NetCard,1 ; network installed ?
JNZ NetNotFound ; brif not,
TEST AH,ALTDown ; alt key down ?
JNZ NOTFND ; brif so, without eating ctrl-alt-brk
NetNotFound:
TEST AH,ALTDown ; was ALT also down ?
JNZ OTHRET ;EAT CTRL ALT BRK
TEST PPBEBL,01H ;BREAK key trapping enabled ?
JZ NOTFND ;Brif not
CMP WASPOS,0 ;CTRL PAUSE active ?
JZ BRKCH1 ;Brif not
JMP SHORT SETPOS ;else report this as ^S
BRKCH1:
MOV BRKFLG,1 ;else set BREAK key flag
CALL B$IBreak ;notify interpreter of BREAK
OTHRET:
STC ;indicates key found
RET
NOTFND:
CLC ;indicates key not found
RET
;**
;Control branches here if no trappable key was
;hit. This routine lets all other keys to go
;through the ROM keyboard interrupt handler
;IF AND ONLY IF CTRL PAUSE is NOT active. If
;CTRL PAUSE is active then it reports that key as
;another CTRL PAUSE if it is NOT any of the SHIFT
;keys.
NONE:
CMP WASPOS,0 ;CTRL PAUSE active ?
JZ NONE2 ;Brif not
CALL SHKEYS ;else check for shift keys
JC NONE1 ;Brif it is a shift key
MOV POSFLG,1 ;else report it as CTRL PAUSE
JMP KBDRET ;set EVTFLG and return
NONE1:
CMP CX,3 ; was it CTRL, LEFT-SHIFT or RIGHT-SHIFT?
JBE NONE2 ; brif so -- let it go through
JMP KBDRET ;EAT ALL OTHER SHIFT KEYS
NONE2: ;comes here if CTRL PAUSE not
;active and no trapping occured
CLC ;clear carry
MOV AX,KEYHIT ; restore key hit
JMP ROMINT ;pass control to ROM INTERRUPT
;i.e. pass the key to the input stream
;******************************************************
;SHKEYS is used to find out if the key hit
;is one of the following:
; INS, CAPSLOCK, NUMLOCK, SCROLLLOCK, ALT,
; CTRL, LEFTSHIFT, RIGHTSHIFT.
; If the key hit is one of the above it returns
; with carry set else returns with carry clear.
; Also if it is the CTRL key it returns the
; value 3 in [CX]. If PAUSE is active then typing
; any of these keys will not release pause, and
; except for CTRL all other shift keys are EATEN
; by B$KBDTRP.
;******************************************************
SHKEYS: ; AL = scan code
MOV DI,OFFSET DGROUP:SHFTBL
MOV CX,9 ;count of 8 keys
CLD ;to be safe
REPNZ SCASB ;search for a shift key
CLC ; clear carry
JCXZ SHKRET ; Brif none found
STC
SHKRET:
RET
PAGE
;***
;B$HookKbd - Hook keyboard interrupt
;
;Purpose:
; Added with revision [13].
; The QB4 user interface needs to have control of the
; keyboard interrupt when it is active to avoid conflicts
; with TSR programs like SIDEKICK. When the user interface
; is exitting, it will deinstall it's handler and call
; this routine so that the runtime can reinstall our keyboard
; handler.
;Entry:
; None.
;Exit:
; None.
;Uses:
; Per Convention.
;Exceptions:
; None.
;******************************************************************************
cProc B$HookKbd,<PUBLIC,FAR>
cBegin
AND b$EventFlags,NOT KybdInst ; force re-installation of
; keyboard interrupt handler
XOR AL,AL ; get current key status,
; flush keystrokes, and
CALL B$RDKYBD ; hook int 9
cEnd
PAGE
;***
;B$UnHookKbd - UnHook runtime keyboard interrupt
;
;Purpose:
; The QB4 user interface needs to have control of the
; keyboard interrupt when it is active to avoid conflicts
; with TSR programs like SIDEKICK. When the user interface
; is entering, it will call this routine and the runtime will
; unhook itself from the keyboard interrupt chain. The user
; interface will then install its keyboard handler.
;Entry:
; None.
;Exit:
; None.
;Uses:
; Per Convention.
;Exceptions:
; None.
;******************************************************************************
cProc B$UnHookKbd,<PUBLIC,FAR>
cBegin
XFRINT KYBINT,KBDVEC/4 ;restore original INT 9 (saved in EF)
cEnd
;***
;B$InitKeys1 - Init some event stuff
;OEM-interface routine
;
;Purpose:
; Init some event stuff.
;
;Entry:
; AL = value to pass to B$RDKYBD when DX = Ctl_Creak
;
;Exit:
; None.
;
;Uses:
; Per Convention.
;
;Exceptions:
; None.
;
;******************************************************************************
cProc B$InitKeys1,<PUBLIC,NEAR>
cBegin
MOV [B$IPOLKEY],EV_TEXTOFFSET B$POLKEY
TEST b$CtrlFlags,DSwitch ;has B$DBINI done this already?
jnz inidon ;brif so
PUSH AX ;save this value for later
MOV SI,EV_TEXTOFFSET B$RDKYBD ;stick in reg to make
mov al,enable_trap ; code smaller & faster
mov dx,printer_echo ;enable the printer echo
call si
mov dx,pause_key ;enable pause key
call si
POP AX ;retrieve input value
mov dx,Ctl_Break ;en/disable ^Break trapping (depending on AL)
call si
mov al,start_key ;start key trapping
call si
inidon:
cEnd
SUBTTL Keyboard Interrupt/Trap Checking in an Operating System Environment
PAGE
;***
;B$POLKEY -
;OEM-interface Routine
;
;Purpose:
; Process keys trapped by the OEM/machine dependent keytrapping
; support.
; Algorithm:
;
; Set b$CntlC to 0
; Call OEM routine B$RDKYBD to detect if a key event has occurred.
; If trapped key then
; report to KEYTRP
; If ^C then
; Set b$CntlC to 1
; If ^S then
; toggle the ^S flag
; If <printer-echo>
; toggle the printer echo flag
; Loop to call B$RDKYBD until no more key events are reported.
; If ^S flag is set then
; loop to call B$RDKYBD until another ^S event is detected.
;Entry:
; none
;
;Exit:
; none
;
;Uses:
; none
;
;Exceptions:
; none
;
;****
cProc B$POLKEY,<PUBLIC,NEAR>,<AX,BX>
cBegin ; - this routine was completely
; rewritten - mostly taken from
; the interpreter
Pollop:
xor ax,ax ;Read trapped keys function code
call B$RDKYBD ;OEM dependent key trap routine
dec bx
jns Waskey ;Function, arrow, or user def. key trapped
inc bx
jz Polkyx ;No key was trapped
inc bx
jz Wasctc ;^C / <break> function
inc bx
jz Wascts ;^S / <pause> function
inc bx
jnz Pollop ;Not <print-screen> func. - ignore, poll next
Wasctp: ;<printer echo> function
XOR b$IOFLAG,LPR_ECHO ; Toggle the printer echo flag
jmp short Pollop ;Key found, so there may be more
Waskey:
; Trap zero relative key if event is ON
xchg ax,bx
ADD AL,KEYOFF ; [AL] = 0-relative event id
CALL B$TestTrap
JZ Pollop
CALL B$ReqTrap ; Trap enabled, Issue Request
jmp short Pollop ; Key found, so there may be more
Wascts: ;^S / <pause> function
XOR b$EventFLags,PAUSEF ; Toggle the pause flag
jmp short Pollop ;Key found, so there may be more
Wasctc: ;flag ^Break found
OR b$EventFlags,CNTLC ; ^Break is reported last so
AND b$EventFlags,NOT PAUSEF ; turn off pause and exit
Polkyx:
TEST b$EventFlags,PAUSEF ; Test for pause processing
jnz Pollop ;Pause in process, wait for "unpause"
cEnd
sEnd EV_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -