📄 woarlm.asm
字号:
mov bx,OriginalDosBlockSize ;get the original size
mov ax,4a00h ;resize call
int 21h ;dos block resized
; now set back the original arena type.
mov ax,es ;currently pointing to the block
dec ax ;the arena segment
mov es,ax ;point to the arena
mov al,OriginalBlockType ;get the actual arena type
mov es:[0],al ;restore it
; now switch back to WOA PDB
mov bx,WoaPSP ;WOA PDB segment
mov ax,5000h ;set PDB call
int 21h ;back to legal PDB
; we can now go back in protected mode and swap windows in.
pop ax ;get back exec code
popf ;get back flags
jc @f ;if error, do not reset ax
xor ax,ax ;to signify that old app exited
@@:
mov bx,WoaInt15UsershApp ;return ID of guy using INT 15
ret
RealModeWoa endp
;----------------------------------------------------------------------------;
; WOA HOOKED INTERRUPT HANDLERS ;
;----------------------------------------------------------------------------;
;----------------------------------------------------------------------------;
; Int1CISR: ;
; ;
; The Switcher hooks this interrupt to timeout Switch requests that cannot ;
; be satisfied within a resonable frame of time. The number of timer ints ;
; that we wait since a SwitchOut Request has been made is governed by a ;
; constant. ;
; ;
; Also, if we are in the middle of a switch, we should reset the tickcount ;
; and activate it again when we are done with the switch. ;
;----------------------------------------------------------------------------;
Int1CISR proc far
test cs:[WoaHotkeyState],WOA_SWITCH
jz Int1CNoSwReq ;no switch request has been registered
inc cs:[PendingTime] ;we have seen one more tick
; have we waited long enough.
cmp cs:[PendingTime],TIMEOUT_TICK_COUNT
jae Int1CAbortSwitch ;abort the switch.
jmp short ChainInt1COn ;chain it on.
Int1CNoSwReq:
mov cs:[PendingTime],0 ;reset
jmp short ChainInt1COn ;chain it on.
Int1CAbortSwitch:
; if we are in the process of switching, do not reset the hotkeystate.
test cs:[SwitchInProgress],SIP_SWITCHING
jnz ChainInt1COn ;in the middle of switching
mov cs:[WoaHotkeyState],0 ;reset the switch request
call OEMBeep ;let user know about this
ChainInt1COn:
jmp cs:[ActualInt1C] ;chain it on.
Int1CISR endp
;----------------------------------------------------------------------------;
; Int09ISR: ;
; ;
; This traps the keyboard hardware interrupt. It detects the types of keys ;
; and sets flags when it detects the HOT KEYS. It also passes control to the ;
; original Int09 handler once it is done with the checkings. ;
; ;
; We have a local list of HotKeys and each app in the shell stublet will have;
; it's own hotkeys. Both these lists have to be scanned. ;
;----------------------------------------------------------------------------;
Int09ISR proc far
; because of the hot key search, we might take some time in this routine.
; we will enable interrupts here.
sti ;enable interrupts
push ds
push ax ;save callers data seg and ax
; if 'fNoSwitch' flag is set, simply chain on the interrupt.
test cs:[WoaBehavior],fNoSwitch;switch prevented ?
jnz ChainInt09ISR ;chain on
; read the key and the scan code.
xor ax,ax ;need access to 0:
mov ds,ax ;DS points to seg at 0:
; read in the key code.
in al,60h ;al has the code for the key pressed
mov ah,ds:[KEYSTATE] ;get the state flag
and ah,0fh ;mask off the unused bits
smov ds,cs ;get the code seg
assumes ds,StubSeg
; we are assuming that we will not have any valid hotkey without SHIFT, CTRL
; or ALT.
jz LeaveInt09ISR ;can't be a hot key
test ah,3 ;any shift key down ?
jz @f ;no
or ah,3 ;both shift keys down
@@:
; try to find a match in the hotkey list
pushem ax,dx ;save
call MatchHotKeyList ;try to match against know hotkeys
popem ax,dx ;restore scan code and shift state
jnc EndInt09ISR ;a match was found, end the int
; we did not find a match in the hot key list, must chain the INT on.
LeaveInt09ISR:
; save the last key so that keys which need to check for the extended key
; sequences may look at it (like 0eh 37h is PRTSC but just 37h is NUMPAD '*')
mov LastScanCode,al ;save the last scan code
ChainInt09ISR:
pop ax
pop ds ;restore the registers
assumes ds,nothing
jmp cs:[ActualInt09] ;jump down the chain
EndInt09ISR:
mov LastScanCode,al ;save the last scan code
call SwallowKey ;eat up the interrupt
pop ax
pop ds ;restore the registers
iret ;and go back
Int09ISR endp
;----------------------------------------------------------------------------;
; MatchLocalHotKeyList: ;
; ;
; This takes a scan code in AL and a shift state in AH and looks for a match ;
; in the local hot key list. If a match is found, AL will return the switch ;
; type and carry will be reset else carry will be set and AL will return 0. ;
; This routine will also OR in the switch out flags if a match is found. ;
;----------------------------------------------------------------------------;
MatchHotKeyList proc near
assumes ds,StubSeg
pushem bx,cx,di,es ;save
smov es,ds ;load our segment
; see if there is a match in the table of scan codes.
mov di,StubSegOFFSET ScanCodeTable
mov cx,MAX_NUM_PROGRAMS+MAX_FIXED_HOT_KEYS
cld ;set proper direction flag
MHKL_Loop:
repne scasw ;look for a match
jnz MHKL_NoMatch ;no match found
; get the index of the matching node.
push di ;save
sub di,2 ;back over to the matching one
.errnz SIZE ScanCodeStruc - 2
sub di,StubSegOFFSET ScanCodeTable
; see if a prefix scan code is required and if it matches, if it does, get
; the other details. Also, make sure that the key has not been disabled.
shl di,1 ;offset into other table
.errnz SIZE HotKeyInfoStruc - 4
add di,StubSegOFFSET HotKeyInfoTable
; now there are two things to match here. The key must be enabled (that is,
; HKIS_State must be 0) and if the prefix scan code is not 0, it should match
; the LastScanCode.
xor bx,bx ;BL=enable state, BH needed for other
mov dx, wptr [di.HKIS_State];get enable flag and prefix scan code
cmp bh,dh ;carry set if DH is not 0
sbb bh,0 ;BH=0 if DH = 0, else it is 0FFH
and bh,LastScanCode ;BH = LastScanCode if DH !=0, else 0
cmp bx,dx ;do they match ?
jnz MHKL_Continue ;no, look for another
mov dl,[di.HKIS_NodeNum] ;logical node number
; if we are trying to hot-key to the current app, we should just pretend that
; the hot key did not match.
cmp dl,AppsLogicalNodeNum ;is it the current app ?
jz MHKL_Continue ;yes, look for another
pop bx ;balance the stack, don't need saved di
; we have found a hot key, get all the details.
mov al,[di.HKIS_Type] ;type of the switch
or WoaHotkeyState,al ;save the return value
mov WoaNodeToSwitchTo,dl ;save the app's NodeID
clc ;match obtained
jmp short MHKL_Ret ;done.
MHKL_Continue:
pop di ;points after last match
jcxz MHKL_NoMatch ;no more to search
jmp short MHKL_Loop ;continue looking for more
MHKL_NoMatch:
stc ;no match obtained
MHKL_Ret:
popem bx,cx,di,es ;save
ret
MatchHotKeyList endp
;----------------------------------------------------------------------------;
; PrepareAppHotKeyList: ;
; ;
; This routine traverses the global switcher structure and fills in the table;
; of Scan codes and hotkey information in the two corresponding tables. This ;
; done once before starting the app and after every switch back to the app. ;
;----------------------------------------------------------------------------;
PrepareAppHotKeyList proc near
assumes ds,StubSeg
; first zero out the scan code and hotkey info tables that are specific to
; apps.
push es ;save
cld
smov es,ds ;load our segment into es
xor ax,ax ;will zero out
mov di,StubSegOFFSET AppsScanCodeTable
mov cx,MAX_NUM_PROGRAMS * SIZE ScanCodeStruc
rep movsb ;zero out first table
mov di,StubSegOFFSET AppsHotKeyInfoTable
mov cx,MAX_NUM_PROGRAMS * SIZE HotKeyInfoStruc
rep movsb ;zero out first table
; now rebuild the tables.
les di,lpGlobalSwtchStr ;get a pointer to the structure
xor bx,bx ;start at the top of the table
mov cx,MAX_NUM_PROGRAMS ;number of entries
mov dl,SIZE Switch_Entry ;size of each entry
; walk through the list gathering information about scan codes and hot keys.
xor ah,ah ;zero out for 'mul' below
mov al,es:[di].First_In_list;get the first entry
mul dl ;ax has the node offset
lea si,[di].Program_List ;es:si points to the first program entry
add si,ax ;point to the right node.
xor dh,dh ;logical node number
PAHKL_Loop:
; stuff in the scan codes.
mov al,es:[si].HK_Scan_Code_2 ;second scan code
mov AppsScanCodeTable[bx.SCS_ScanCode],al ;save scan code.
mov al,es:[si].HK_Shift_State ;get the shift state
; if any shift bit is set, set both.
test al,ST_RSHIFT+ST_LSHIFT ;any shift set ?
jz @f ;no.
or al,ST_RSHIFT+ST_LSHIFT ;set both.
@@:
mov AppsScanCodeTable[bx.SCS_ShiftState],al ;save shift state
; save the rest of the information about the hotkeys in the other table
shl bx,1 ;index into the other table
.errnz SIZE HotKeyInfoStruc - SIZE ScanCodeStruc * 2 ;assert the assumption
mov AppsHotKeyInfoTable[bx.HKIS_State],0 ;enabled
mov al,es:[si].HK_Scan_Code_1 ;first scan code
mov AppsHotKeyInfoTable[bx.HKIS_PrefixScanCode],al;prefix scan code
mov AppsHotKeyInfoTable[bx.HKIS_NodeNum],dh ;save shift state
mov AppsHotKeyInfoTable[bx.HKIS_Type],WOA_ALT_ESC ;type of switch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -