home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d483
/
pwkeys
/
pwkeys.asm
< prev
next >
Wrap
Assembly Source File
|
1991-05-10
|
32KB
|
1,213 lines
* PWKeys V1.0
* By Preben Nielsen
*
* PWKeys is an input-handler that allows you to manipulate windows
* and screens by pressing keys on the keyboard (a lot faster than
* using the mouse).
*
* Once installed, the program only uses 1124 bytes of memory. To
* remove PWKeys simply run the it again.
*
* NOTE: There's no need to 'RUN' or 'RUNBACK' this program from the
* CLI. It terminates immediately.
*
*HISTORY
* Made with Hisoft V2.12
*
* V1.0 20-Apr-91: This is first release. I made it over a year ago
OPT O+
OPT O1+ ; Tells when a branch could be optimised to short
OPT i+ ; Tells when '#' is probably missing
include "PWKeys.i"
incdir "AsmInc:"
include "exec/exec_lib.i"
include "exec/io.i"
include "exec/memory.i"
include "exec/interrupts.i"
include "devices/input.i"
include "devices/inputevent.i"
include "libraries/dos.i"
include "libraries/dos_lib.i"
include "libraries/dosextens.i"
include "graphics/layers.i"
include "intuition/intuition.i"
include "intuition/intuitionbase.i"
include "intuition/intuition_lib.i"
include "Workbench/startup.i"
include "Workbench/workbench.i"
include "Workbench/icon_lib.i"
Prepare MACRO
IFC '\1','Exec_Call'
movea.l 4.W,A6
ENDC
IFC '\1','Icon_Call'
movea.l IconBase(DB),A6
ENDC
IFC '\1','Intuition_Call'
movea.l IntBase(DB),A6
ENDC
IFC '\1','Gfx_Call'
movea.l GfxBase(DB),A6
ENDC
IFC '\1','Dos_Call'
movea.l DosBase(DB),A6
ENDC
ENDM
CallLib MACRO
jsr _LVO\1(A6)
ENDM
Call MACRO
bsr \1
ENDM
CallS MACRO
bsr.S \1
ENDM
Push MACRO
movem.l \1,-(SP)
ENDM
Pop MACRO
movem.l (SP)+,\1
ENDM
rAPtr MACRO name
DefSiz set DefSiz+4
DefPtr set DefPtr-4
\1 = DefPtr
ENDM
rLong MACRO name
DefSiz set DefSiz+4
DefPtr set DefPtr-4
\1 = DefPtr
ENDM
rWord MACRO name
DefSiz set DefSiz+2
DefPtr set DefPtr-2
\1 = DefPtr
ENDM
rByte MACRO name
DefSiz set DefSiz+1
DefPtr set DefPtr-1
\1 = DefPtr
ENDM
rStorage MACRO name,size ; Define storage
DefSiz set DefSiz+\2
DefPtr set DefPtr-\2
\1 = DefPtr
ENDM
rEVEN MACRO ; Word boundary
IFNE DefPtr&1
DefPtr set DefPtr-1
DefSiz set DefSiz+1
ENDC
ENDM
rStart MACRO ; Define var section
DefPtr set 0
DefSiz set 0
ENDM
rEnd MACRO ; End var section
RelSize = DefSiz
ENDM
rAlloc MACRO ; Allocate vars
link DB,#-RelSize
ENDM
rFree MACRO ; Deallocate vars
unlk DB
ENDM
rClear MACRO ; Reset all vars
movem.l D0/DB,-(SP)
move.w #RelSize-1,D0
rClr.\@ clr.b -(DB)
dbf D0,rClr.\@
movem.l (SP)+,D0/DB
ENDM
DB EQUR A4
SECTION PWKeys,CODE
InitProcess rAlloc ; Allocate memory for variables
rClear ; Clear the memory
subq.l #1,D0
move.l A0,CName(DB)
move.l D0,CLen(DB)
Prepare Exec_Call
CallLib Forbid
lea IHS(PC),A1
lea ihs_PortName(A1),A1
CallLib FindPort
move.l D0,HPort(DB)
CallLib Permit
suba.l A1,A1
CallLib FindTask ; Find us
move.l D0,PProcess(DB)
movea.l D0,A2
tst.l pr_CLI(A2)
bne.S CLIStart
WBStart lea pr_MsgPort(A2),A0
CallLib WaitPort ; wait for a message
lea pr_MsgPort(A2),A0
CallLib GetMsg ; then get it
move.l D0,WBMsg(DB) ; save it for later reply
bra.S GetLibs
CLIStart move.l CName(DB),A0
move.l CLen(DB),D0
clr.b 0(A0,D0.W)
GetLibs lea DosName(PC),A1
CallLib OldOpenLibrary
move.l D0,DosBase(DB)
beq Error
lea IntName(PC),A1
CallLib OldOpenLibrary
move.l D0,IntBase(DB)
beq Error
tst.l HPort(DB) ;Install or Remove ?
bne.S LetsBegin
tst.l WBMsg(DB)
beq.S LetsBegin ;CLI or WB ?
clr.l CLen(DB) ;Signal that we haven't found args yet
move.l WBMsg(DB),A2
move.l sm_NumArgs(A2),D0 ;Any args ?
move.l sm_ArgList(A2),A2
subq.l #1,D0
blt.S LetsBegin
beq.S FoundArg
addq.w #wa_SIZEOF,A2 ;Project
FoundArg move.l wa_Lock(A2),D1
move.l wa_Name(A2),A2 ;Name of icon
beq.S NoLock
Prepare Dos_Call
CallLib CurrentDir
NoLock Prepare Exec_Call
lea IconName(PC),A1
CallLib OldOpenLibrary
move.l D0,IconBase(DB)
beq.S LetsBegin
Prepare Icon_Call
move.l A2,A0
CallLib GetDiskObject ;Get the icon
move.l D0,DiskObj(DB)
beq.S LetsBegin
move.l D0,A2
move.l do_ToolTypes(A2),A0
lea FileTxt(PC),A1
CallLib FindToolType ;Find 'FILE=??????'
move.l D0,CName(DB)
move.l D0,CLen(DB) ;Signal that we have or haven't found args
LetsBegin tst.l HPort(DB)
beq.S DoInstall
DoRemove moveq #REMOVED,D7
lea IHS(PC),A0
lea PSEndIHS1(PC),A1
lea PSEndIHS2(PC),A2
Call RemoveHandler
beq.S ShowMsg
moveq #CANTREMOVE,D7
bra.S ShowMsg
DoInstall moveq #INSTALLED,D7
lea IHS(PC),A0
lea PSPrepIHS1(PC),A1
lea PSPrepIHS2(PC),A2
Call InstallHandler
beq.S ShowMsg
moveq #CANTINSTALL,D7
ShowMsg move.l D7,D0
Call CONMsg
Error
Exit Prepare Exec_Call
FreeDos move.l DosBase(DB),D0
beq.S ReplyWB
move.l D0,A1
CallLib CloseLibrary
ReplyWB move.l WBMsg(DB),D0
beq.S AllDone
move.l DiskObj(DB),D0
beq.S FreeIcon
move.l D0,A0
Prepare Icon_Call
CallLib FreeDiskObject
FreeIcon Prepare Exec_Call
move.l IconBase(DB),D0
beq.S WBEnd
move.l D0,A1
CallLib CloseLibrary
WBEnd CallLib Forbid ; We were started from WB
move.l WBMsg(DB),A1
CallLib ReplyMsg ; Reply WBMessage
AllDone rFree
moveq #0,D0
rts
FHandle EQUR D5
* Call: D0 = Msg-number
CONMsg Push D0-D7/A0-A6
Prepare Dos_Call
move.l D0,D4
moveq #0,D6
CallLib Output
move.l D0,FHandle
bne.S 1$
moveq #1,D6
lea CONName(PC),A0
move.l A0,D1
move.l #MODE_OLDFILE,D2
CallLib Open
move.l D0,FHandle
beq.S 2$
1$ moveq #INFOMSG,D0
Call SendMsg
move.l D4,D0
Call SendMsg
tst.l D6
beq.S 2$
moveq #127,D1
CallLib Delay
move.l FHandle,D1
CallLib Close
2$ Pop D0-D7/A0-A6
rts
* Call: D0 = Msg-number
SendMsg neg.l D0
lsl.l #1,D0
lea MsgTable(PC),A0
add.w 0(A0,D0),A0
move.l A0,D2
moveq #-1,D3
1$ addq.l #1,D3
tst.b (A0)+
bne.S 1$
move.l FHandle,D1
Prepare Dos_Call
CallLib Write
rts
INFOMSG =0
INSTALLED =-1
REMOVED =-2
CANTINSTALL =-3
CANTREMOVE =-4
MsgText MACRO
dc.w \1-MsgTable
ENDM
MsgTable MsgText Msg
MsgText Msg1
MsgText Msg2
MsgText Msg3
MsgText Msg4
CONName dc.b 'CON:100/60/330/63/PWKeys',0
Msg dc.b 10,$9B,'0;33m PWKeys V1.0',10
dc.b $9B,'0;31m 1991 by ',$9B,'0;33mPreben Nielsen',$9B,'0;31m',10,' ',0
Msg1 dc.b 'has just been installed...',10,0
Msg2 dc.b 'has just been removed...',10,0
Msg3 dc.b 'Error: Cannot install handler',10,0
Msg4 dc.b 'Error: Cannot remove handler',10,0
EVEN
rtsValue EQUR D7
* This is general-purpose inputhandler removal-routine
* It only needs an ihs with a port-name to remove the handler
* Call: A0 = ihs
* A1 = first ihs-installation-routine or NULL
* A2 = second ihs-installation-routine or NULL
* Return: D0 = 0 means succes
RemoveHandler Push D1/rtsValue/A0-A3/A6
moveq #-1,rtsValue
move.l A2,A3
move.l A0,A2
move.l A1,D1
beq.S 1$
jsr (A1) ; A0 = ihs
beq.S 2$
move.l D0,A2
1$ move.l A2,A0
Prepare Exec_Call
moveq #IND_REMHANDLER,D0
Call TellInputDevice
move.l D0,rtsValue
bne.S 2$
lea ihs_Port(A2),A1
CallLib RemPort
moveq #0,D0
bra.S 3$
2$ moveq #-1,D0
3$ move.l A3,D1
beq.S 4$
move.l A2,A0
jsr (A3) ; A0 = ihs, D0 = 0 means succes
4$ move.l rtsValue,D0
Pop D1/rtsValue/A0-A3/A6
rts
* This is general-purpose inputhandler installation-routine
* It only needs an ihs with a port-name to install the handler
* Call: A0 = ihs
* A1 = first ihs-installation-routine or NULL
* A2 = second ihs-installation-routine or NULL
* Return: D0 = 0 means succes
InstallHandler Push D1/rtsValue/A0-A3/A6
moveq #-1,rtsValue
move.l A2,A3
move.l A0,A2
move.l A1,D1
beq.S 1$
jsr (A1) ; A0 = ihs
beq.S 2$
move.l D0,A2
1$ move.l A2,A0
moveq #IND_ADDHANDLER,D0
Call TellInputDevice
move.l D0,rtsValue
bne.S 2$
lea ihs_Port(A2),A1
lea ihs_PortName(A2),A0
move.l A0,MP+LN_NAME(A1) ;MsgPort->mp_Node.ln_Name=Name;
clr.b MP+LN_PRI(A1) ;MsgPort->mp_Node.ln_Pri =0;
move.b #NT_MSGPORT,MP+LN_TYPE(A1) ;MsgPort->mp_Node.ln_Type=NT_MSGPORT;
move.b #PA_IGNORE,MP_FLAGS(A1) ;MsgPort->mp_Flags =PA_IGNORE;
Prepare Exec_Call
CallLib AddPort
moveq #0,D0
bra.S 3$
2$ moveq #-1,D0
3$ move.l A3,D1
beq.S 4$
move.l A2,A0
jsr (A3) ; A0 = ihs, D0 = 0 means succes
4$ move.l rtsValue,D0
Pop D1/rtsValue/A0-A3/A6
rts
* Open the input device. Set up the I/O block to add or remove the
* input handler, and send the request to the input device. Finally,
* close the device
* Call: A0 = ihs
* D0 = Function to perform (IND_ADDHANDLER/IND_REMHANDLER)
* Return: D0 = 0 means succes
TellInputDevice Push D1-D2/rtsValue/A0-A3/A6
Prepare Exec_Call
moveq #-1,rtsValue
move.l D0,D2
move.l A0,A2
lea IReq(DB),A0
moveq #IOSTD_SIZE,D0
Call MemClear
lea IPort(DB),A0
moveq #MP_SIZE,D0
Call MemClear
move.l A0,A3
move.b #NT_MSGPORT,MP+LN_TYPE(A3) ; mp_Node.ln_Type=NT_MSGPORT;
move.b #PA_SIGNAL,MP_FLAGS(A3) ; mp_Flags =PA_SIGNAL;
moveq #-1,D0
CallLib AllocSignal
move.b D0,MP_SIGBIT(A3) ; mp_SigBit =MPSigBit;
bmi.S 2$
suba.l A1,A1
CallLib FindTask
move.l D0,MP_SIGTASK(A3) ; mp_SigTask =FindTask(0);
lea IReq(DB),A1
move.l A3,IO+MN_REPLYPORT(A1) ; ExtReq->io_Message.mn_ReplyPort =taskReplyPort;
move.b #NT_MESSAGE,IO+MN+LN_TYPE(A1) ; ExtReq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
lea InputName(PC),A0 ; input.device
moveq #0,D0 ; unit#
moveq #0,D1 ; flags
CallLib OpenDevice
tst.w D0 ; flag: error if > 0
bne.S 1$
lea IReq(DB),A1
move.w D2,IO_COMMAND(A1)
lea ihs_Interrupt(A2),A0
move.l A0,IO_DATA(A1)
CallLib DoIO
move.l D0,rtsValue
lea IReq(DB),A1
CallLib CloseDevice
1$ move.b MP_SIGBIT(A3),D0
CallLib FreeSignal
2$ move.l rtsValue,D0
Pop D1-D2/rtsValue/A0-A3/A6
rts
* Call: A0 = Memory area
* D0:16 = Count
MemClear Push D0-D1/A0
moveq #0,D1
bra.S 2$
1$ move.b D1,(A0)+
2$ dbf D0,1$
Pop D0-D1/A0
rts
* Call: A0 = Source
* A1 = Destination
* D0:16= Count
MemCopy Push D0/A0-A1
bra.S 2$
1$ move.b (A0)+,(A1)+
2$ dbf D0,1$
Pop D0/A0-A1
rts
* Each handler should have such a pair of installation-routine
* The first one is passed to InstallHandler in A1 and it
* is called immediately when entering InstallHandler
* The second one is passed to InstallHandler in A2 and it
* is called after attempt to install handler and message-port
* -----------------------------------------------------------------
* Call: A0 = ihs
* Return: D0 has to point to ihs to be used when installation proceeds
* If D0 = 0 then installation is aborted
PSPrepIHS1 Push D1/A0-A1/A6
Call GetKeys
beq.S 2$
lea IntuiBase(PC),A1
move.l IntBase(DB),(A1)
Prepare Exec_Call
move.l #HandlerSize,D0
move.l #MEMF_PUBLIC|MEMF_CLEAR,D1
CallLib AllocMem
move.l D0,HMem(DB)
beq.S 2$
move.l D0,A1
lea IHS(PC),A0
move.l #HandlerSize,D0
Call MemCopy
move.l D0,ihs_Length(A1) ; This will enable removal by other programs
lea HandlerCode-IHS(A1),A0
move.l A0,ihs_Interrupt+IS_CODE(A1) ; HandlerBlock.HInterrupt.is_Code = Handler
lea PWKVersionID-IHS(A1),A0
move.l A0,ihs_Interrupt+IS_DATA(A1) ;HandlerBlock.HInterrupt.is_Data = KeyDefines;
move.b PWKPri(PC),ihs_Interrupt+LN_PRI(A1);HandlerBlock.HInterrupt.is_Node.ln_Pri = PRI;
move.l A1,D0
2$ Pop D1/A0-A1/A6
rts
* Call: A0 = ihs
* D0 = 0 means everything went perfect
* -1 means something went wrong during installation
PSPrepIHS2 Push D0-D1/A0-A1/A6
tst.l D0
beq.S 1$
move.l HMem(DB),D0
beq.S 1$
move.l D0,A1
move.l #HandlerSize,D0
Prepare Exec_Call
CallLib FreeMem
1$ Pop D0-D1/A0-A1/A6
rts
* Each handler should have such a pair of ending-routine
* The first one is passed to RemoveHandler in A1 and it
* is called immediately when entering RemoveHandler
* The second one is passed to RemoveHandler in A2 and it
* is called after attempt to remove handler and message-port
* -----------------------------------------------------------------
* Call: A0 = ihs
* Return: D0 has to point to ihs to be used when removal proceeds
* If D0 = 0 then removal is aborted
PSEndIHS1 Push D1-D2/A0-A1/A6
Prepare Exec_Call
CallLib Forbid
lea ihs_PortName(A0),A1
CallLib FindPort
move.l D0,D2
CallLib Permit
move.l D2,D0 ; Does Forbid/Permit destroy scratch-registers ?
Pop D1-D2/A0-A1/A6
rts
* Call: A0 = ihs
* D0 = 0 means everything went perfect
* -1 means something went wrong during removal
PSEndIHS2 Push D0-D1/A0-A1/A6
tst.l D0
bmi.S 1$
Prepare Exec_Call
move.l ihs_Length(A0),D0
move.l A0,A1
CallLib FreeMem
1$ Pop D0-D1/A0-A1/A6
rts
* Tries to read hotkeys from file (if any is specified)
* Return: D0 = 0 means failure
GetKeys Push D1-D7/A0-A6
moveq #1,rtsValue
tst.l CLen(DB)
beq.S 2$
moveq #0,rtsValue
Prepare Dos_Call
move.l CName(DB),D1
move.l #MODE_OLDFILE,D2
CallLib Open
move.l D0,D4
beq.S 2$
move.l D0,D1
lea TempFile(PC),A0
move.l A0,D2
move.l #FilePart,D3
CallLib Read
cmp.l D0,D3
bne.S 1$
movem.l TempFile(PC),D0-D1
movem.l PWKVersionID(PC),D2-D3
cmp.l D0,D2
bne.S 1$
cmp.l D1,D3
bne.S 1$
lea TempFile(PC),A0
lea PWKVersionID(PC),A1
move.l #FilePart,D0
Call MemCopy
moveq #1,rtsValue
1$ move.l D4,D1
CallLib Close
2$ move.l rtsValue,D0
Pop D1-D7/A0-A6
rts
* This is buffer when trying to read file
TempFile dc.l 'PWKF'
dc.w PWKeysVersion,PWKeysRevision
dc.b PWKeysPri,0
dc.w DefFuncNumber
TemPWKeys dcb.b FilePart-12
*====================== Input-handler start =========================
ihs_Port =0
ihs_Interrupt =MP_SIZE
ihs_ID =MP_SIZE+IS_SIZE
ihs_Length =MP_SIZE+IS_SIZE+4
ihs_Flags =MP_SIZE+IS_SIZE+8
ihs_PortName =MP_SIZE+IS_SIZE+10
ihs_Start MACRO
dcb.b MP_SIZE ; Message-Port structure
dcb.b IS_SIZE ; Interrupt structure
dc.l 'P_IH' ; ID (Handler made by me)
dc.l 0 ; Length of handler
dc.w 0 ; Flags
dc.b \1,0
EVEN
ENDM
HDisabled =0
HNoExtRemoval =1 ; Future
* This is the handler-block
IHS ihs_Start <'PWKeys V1.0 Port'>
* Local variables
Chain dc.l 0
IntuiBase dc.l 0
* This is the beginning of the part coming from a file
PWKVersionID dc.l 'PWKF'
PWKVersionNum dc.w PWKeysVersion,PWKeysRevision
PWKPri dc.b PWKeysPri,0
PWKHotKeys dc.w DefFuncNumber
* These defines are the default when no file is specified
* Keep them sorted on 'Code|Qual'
KeyDefines HotKey KP1,LAMIGA,LAMIGA,AW_TO_LEFT_BOTTOM
HotKey KP2,LAMIGA,LAMIGA,AW_TO_BOTTOM
HotKey KP3,LAMIGA,LAMIGA,AW_TO_RIGHT_BOTTOM
HotKey KP4,LAMIGA,LAMIGA,AW_TO_LEFT
HotKey KP5,LAMIGA,LAMIGA,AW_TO_CENTER
HotKey KP6,LAMIGA,LAMIGA,AW_TO_RIGHT
HotKey KP7,LAMIGA,LAMIGA,AW_TO_LEFT_TOP
HotKey KP8,LAMIGA,LAMIGA,AW_TO_TOP
HotKey KP9,LAMIGA,LAMIGA,AW_TO_RIGHT_TOP
HotKey UPARROW,LAMIGA,LSHIFT|LAMIGA|RAMIGA,AW_TO_BACK
HotKey UPARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA|RAMIGA,FRONT_W_TO_BACK
HotKey UPARROW,RAMIGA,LSHIFT|LAMIGA|RAMIGA,FRONT_S_TO_BACK
HotKey DOWNARROW,LAMIGA,LSHIFT|LAMIGA|RAMIGA,AW_TO_FRONT
HotKey DOWNARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA|RAMIGA,BACK_W_TO_FRONT
HotKey DOWNARROW,RAMIGA,LSHIFT|LAMIGA|RAMIGA,BACK_S_TO_FRONT
HotKey RIGHTARROW,LAMIGA,LAMIGA,ACTIVATE_NEXT_W
HotKey LEFTARROW,LAMIGA,LAMIGA,ACTIVATE_PREV_W
HotKey U_CODE,U_QUAL,U_QUAL,U_FUNC
HotKey U_CODE,U_QUAL,U_QUAL,U_FUNC
HotKey U_CODE,U_QUAL,U_QUAL,U_FUNC
* This is the end of the part coming from a file
* This table below defines the connction between the
* selected hotkey and the function to perform
JmpEntry_SIZE =2
JmpEntry MACRO
dc.w \1-JmpTable
ENDM
JmpTable JmpEntry WindowToTop
JmpEntry WindowToBottom
JmpEntry WindowToLeft
JmpEntry WindowToRight
JmpEntry WindowToTL
JmpEntry WindowToBL
JmpEntry WindowToTR
JmpEntry WindowToBR
JmpEntry WindowToCenter
JmpEntry CurrWinToFront
JmpEntry CurrWinToBack
JmpEntry ActivatePrevWin
JmpEntry ActivateNextWin
JmpEntry BackWinToFront
JmpEntry FrontWinToBack
JmpEntry BackScrToFront
JmpEntry FrontScrToBack
JmpEntry Dummy
JmpEntry Dummy
JmpEntry Dummy
* Handler()
* This is the input handler. For each event in the event list:
* If the event is a raw key event, then
* make the KeyCode longword for that event's code and qualifier,
* binary search the KeyDefines[] array for a matching entry (only consider
* the qualifiers specified by the HotKey_Mask). Since most keys pressed
* will NOT match a hot-key, we want the search to be as fast as
* possible, so we use a binary search rather than a linear search.
* if the key was not a hot key,
* go on to the next key
* otherwise,
* perform the function for the specified hot key,
* remove the hot key from the event list.
* When all the events have been checked, return the event list so that
* Intuition can do its thing.
Max EQUR D4
Min EQUR D5
Num EQUR D6
TheKey EQUR D7
PEvent EQUR A4 ; Previous Event
Event EQUR A5 ; This Event
Next =ie_NextEvent
Class =ie_Class
Code =ie_Code
Qual =ie_Qualifier
* Call: A0 = List of InputEvents, A1 = HandlerData
HandlerCode Push D1-D7/A0-A6
move.w IHS+ihs_Flags(PC),D0
btst #HDisabled,D0 ; Future feature
bne NoMoreEvents
lea Chain(PC),PEvent
move.l A0,Next(PEvent)
ieLoop move.l Next(PEvent),Event
move.l Event,D0
beq.S NoMoreEvents
cmpi.b #IECLASS_RAWKEY,Class(Event)
bne.S DontRemove
DoKey move.w Code(Event),TheKey ; Construct a 'Code|Qual' long-word
swap TheKey
move.w Qual(Event),TheKey
move.w PWKHotKeys(PC),Max ; Do Binary-search
moveq #-1,Min
SearchLoop move.w Max,Num
add.w Min,Num
asr.w #1,Num
cmp.w Num,Min
beq.S DontRemove ; Didn't find a match
move.w Num,D0
lsl.w #3,D0 ; HotKey_SIZE*Num
lea KeyDefines(PC),A2
add.w D0,A2
move.l TheKey,D0
and.l HotKey_Mask(A2),D0 ; TheKey & KeyDefines[Num].HotKey_Mask
cmp.l HotKey_ID(A2),D0 ; A match ?
beq.S Perform
blt.S LookLower
LookHigher move.l Num,Min ; (TheKey & KeyDefines[Num].HotKey_Mask) > KeyDefines[Num].HotKey_ID
bra.S SearchLoop
LookLower move.l Num,Max ; (TheKey & KeyDefines[Num].HotKey_Mask) < KeyDefines[Num].HotKey_ID
bra.S SearchLoop
* Found a match
* A2 = Hotkey
Perform Prepare Exec_Call
CallLib Forbid ; (TheKey & KeyDefines[Num].HotKey_Mask) = KeyDefines[Num].HotKey_ID
moveq #0,D0
move.b HotKey_Func(A2),D0 ; KeyDefines[Num].HotKey_Func
lsl.w #1,D0 ; JmpEntry_SIZE*KeyDefines[Num].HotKey_Func
lea JmpTable(PC),A0
add.w 0(A0,D0.W),A0
move.l IntuiBase(PC),A6 ; Intuitionbase stays loaded
jsr (A0) ; Jump to function
Prepare Exec_Call
CallLib Permit
Remove move.l Next(Event),Next(PEvent); Remove event from chain and move on to next Event
bra.S ieLoop
* Didn't find a match
DontRemove move.l Event,PEvent ; Just move on to next Event
bra.S ieLoop
* Lets return
NoMoreEvents Pop D1-D7/A0-A6
move.l Chain(PC),D0 ; Return (shortened ?) chain
rts
ScreenToBack jmp _LVOScreenToBack(A6)
ScreenToFront jmp _LVOScreenToFront(A6)
WindowToBack Call CheckWindow
bne.S WinErr
jmp _LVOWindowToBack(A6)
WindowToFront Call CheckWindow
bne.S WinErr
jmp _LVOWindowToFront(A6)
ActivateWindow Call CheckWindow
bne.S WinErr
jmp _LVOActivateWindow(A6)
MoveWindow Call CheckWindow
bne.S WinErr
jmp _LVOMoveWindow(A6)
WinErr rts
* Call: A0 = Window to check
* Return: Z-flag set if no active stringgadget or system-gadget
* in the window or in any active requester in the window
CheckWindow Push D0/A1
move.l wd_FirstRequest(A0),D0
beq.S TestWin
ReqCLoop tst.l D0
beq.S WinCEnd
move.l D0,A1
move.w rq_Flags(A1),D0
andi.w #REQACTIVE,D0
beq.S NextReq
move.l rq_ReqGadget(A1),D0
bra.S GadCLoop ; Found an active requester
NextReq move.l rq_OlderRequest(A1),D0
bra.S ReqCLoop
TestWin move.l wd_FirstGadget(A0),D0
* D0 = Gadgetlist
GadCLoop tst.l D0
beq.S WinCEnd
move.l D0,A1
move.w gg_GadgetType(A1),D0
andi.w #SYSGADGET,D0
bne.S CheckSELECT
move.w gg_GadgetType(A1),D0
andi.w #STRGADGET,D0
beq.S NextGad
CheckSELECT move.w gg_Flags(A1),D0
andi.w #SELECTED,D0
beq.S NextGad
moveq #1,D0 ; Window contains an active string-gadget
bra.S WinCEnd ; or an active system-gadget
NextGad move.l gg_NextGadget(A1),D0
bra.S GadCLoop
WinCEnd Pop D0/A1
rts
* TopWindow()
* Find the top window of the specified screen. Start at the top layer of
* the screen and move backward as long as the layer exists and has no
* window connected to it. Return the window associated with the final
* layer, if any.
* Call : A0 = Screen
* Return: D0 = Window or NULL
TopWindow move.l sc_LayerInfo+li_top_layer(A0),A0
moveq #0,D0
1$ move.l A0,D1
beq.S 2$
move.l lr_Window(A0),D0
bne.S 2$
move.l lr_back(A0),A0
bra.S 1$
2$ tst.l D0
rts
* BottomWindow()
* Find the bottom window of the specified screen. Start at the top layer
* and as long as the layer exists, go to the next layer back. If the
* layer has a window attached, consider that to be the bottom window until
* a lower one is found.
* Call : A0 = Screen
* Return: D0 = Window or NULL
BottomWindow move.l sc_LayerInfo+li_top_layer(A0),A0
moveq #0,D0
1$ move.l A0,D1
beq.S 3$
move.l lr_Window(A0),D1
beq.S 2$
move.l D1,D0
2$ move.l lr_back(A0),A0
bra.S 1$
3$ tst.l D0
rts
* NextWindow()
* Find the next window below the specified window (wrap arround to the top
* if the window is the bottom one). Start with the window's layer and go
* back until a layer with a window is found, or no more layers exist. If
* a window was found, return it, otherwise, use the top window.
* Call : A0 = Window
* Return: D0 = Next Window or NULL
NextWindow move.l wd_WLayer(A0),A1
1$ move.l lr_back(A1),A1
move.l A1,D1
beq.S 2$
move.l lr_Window(A1),D0
beq.S 1$
bra.S 3$
2$ move.l wd_WScreen(A0),A0
CallS TopWindow
3$ tst.l D0
rts
* PreviousWindow()
* Find the window that is on top of the specified window (or NULL if there
* are no windows above it). Start with the window's layer, and move to
* the layer in front until a layer with a (different) window is found, or
* until no more layers exist. If a window was found, return it, otherwise
* return NULL.
* Call : A0 = Window
* Return: D0 = Previous Window or NULL
PrevWindow moveq #0,D0
move.l wd_WLayer(A0),A1
1$ move.l lr_front(A1),A1
move.l A1,D1
beq.S 2$
move.l lr_Window(A1),D0
beq.S 1$
cmp.l A0,D0
beq.S 1$
2$ tst.l D0
rts
* BackScrToFront()
* Bring the bottom-most screen to the top, and activate its top window.
* While there is a screen following the current one, move the the next screen.
* Bring that screen to the front and find its top window. If one was found,
* activate the window.
BackScrToFront move.l A2,-(SP)
move.l ib_FirstScreen(A6),A2
1$ move.l sc_NextScreen(A2),D0
beq.S 2$
move.l D0,A2
bra.S 1$
2$ move.l A2,A0
Call ScreenToFront
move.l A2,A0
move.l (SP)+,A2
Call TopWindow
bra.S ActiCommon
* FrontScreenToBack()
* Move the top screen to the back and activate the top window on the new
* top screen.
FrontScrToBack move.l ib_FirstScreen(A6),A0
Call ScreenToBack
move.l ib_FirstScreen(A6),A0
Call TopWindow
bra.S ActiCommon
* ActivatePreviousWindow()
* Get the window previous to the current window (if none, then get the
* bottom window in the active screen), and activate that window.
ActivatePrevWin move.l ib_ActiveWindow(A6),A0
CallS PrevWindow
bne.S ActiCommon
move.l ib_ActiveScreen(A6),A0
Call BottomWindow
bra.S ActiCommon
* ActivateNextWindow()
* Get the window below the current window and activate it.
ActivateNextWin move.l ib_ActiveWindow(A6),A0
Call NextWindow
ActiCommon beq.S 1$
move.l D0,A0
Call ActivateWindow
1$ rts
* CurrentWindowToBack()
* Send the current window to the back of the list.
CurrWinToBack move.l ib_ActiveWindow(A6),D0
beq.S 1$
move.l D0,A0
Call WindowToBack
1$ rts
* CurrentWindowToFront()
* Send the current window to the top of the list.
CurrWinToFront move.l ib_ActiveWindow(A6),D0
beq.S 1$
move.l D0,A0
Call WindowToFront
1$ rts
* BackWindowToFront()
* Move the bottom window to the top and activate it. Get the bottom window,
* skipping over backdrop windows. If one is found, bring it to the front,
* and activate it.
BackWinToFront move.l A2,-(SP)
move.l ib_ActiveScreen(A6),A0
Call BottomWindow
beq.S 3$
1$ move.l D0,A0
move.l A0,D0
beq.S 3$
btst #0,wd_Flags+2(A0) ; BackDrop ?
beq.S 2$
Call PrevWindow
bra.S 1$
2$ move.l A0,A2
Call WindowToFront
move.l A2,D0
beq.S 3$
move.l D0,A0
Call ActivateWindow
3$ move.l (SP)+,A2
rts
* FrontWindowToBack()
* Move the top window to the back, and activate the new top window.
* Get the top window, and then the window following it. Send the top window
* to the back, and activate the next window.
FrontWinToBack Push D2/A2
move.l ib_ActiveScreen(A6),A0
Call TopWindow
beq.S 1$
move.l D0,A0
move.l A0,A2
Call NextWindow
move.l D0,D2
move.l A2,A0
Call WindowToBack
move.l D2,D0
beq.S 1$
move.l D0,A0
Call ActivateWindow
1$ Pop D2/A2
rts
WindowToTop lea TopIt(PC),A1 ; Window To Top
lea DontMoveX(PC),A2
bra.S WindowMove
WindowToBottom lea BottomIt(PC),A1 ; Window To Bottom
lea DontMoveX(PC),A2
bra.S WindowMove
WindowToLeft lea DontMoveY(PC),A1 ; Window To Left
lea LeftIt(PC),A2
bra.S WindowMove
WindowToRight lea DontMoveY(PC),A1 ; Window To Right
lea RightIt(PC),A2
bra.S WindowMove
WindowToCenter lea CenterHeight(PC),A1 ; Window To Center
lea CenterWidth(PC),A2
bra.S WindowMove
WindowToTL lea TopIt(PC),A1 ; Window To Upper Left Corner
lea LeftIt(PC),A2
bra.S WindowMove
WindowToTR lea TopIt(PC),A1 ; Window To Upper Right Corner
lea RightIt(PC),A2
bra.S WindowMove
WindowToBL lea BottomIt(PC),A1 ; Window To Lower Left Corner
lea LeftIt(PC),A2
bra.S WindowMove
WindowToBR lea BottomIt(PC),A1 ; Window To Lower Right Corner
lea RightIt(PC),A2
* A1 = Function to adjust window in y-direction
* A2 = Function to adjust window in x-direction
WindowMove Push A1
move.l ib_ActiveWindow(A6),A0
jsr (A1)
move.w D0,D1
jsr (A2)
bne.S 1$
tst.w D1
beq.S 2$
1$ Call MoveWindow
2$ Pop A1
rts
DontMoveX
DontMoveY moveq #0,D0
Dummy rts
* A0=window
CenterHeight move.l wd_WScreen(A0),A1
move.w sc_Height(A1),D0
sub.w wd_Height(A0),D0
asr.w #1,D0
sub.w wd_TopEdge(A0),D0
rts
* A0=window
CenterWidth move.l wd_WScreen(A0),A1
move.w sc_Width(A1),D0
sub.w wd_Width(A0),D0
asr.w #1,D0
sub.w wd_LeftEdge(A0),D0
rts
* A0=window
BottomIt move.l wd_WScreen(A0),A1
move.w sc_Height(A1),D0
sub.w wd_TopEdge(A0),D0
sub.w wd_Height(A0),D0
rts
* A0=window
RightIt move.l wd_WScreen(A0),A1
move.w sc_Width(A1),D0
sub.w wd_LeftEdge(A0),D0
sub.w wd_Width(A0),D0
rts
* A0=window
TopIt move.w wd_TopEdge(A0),D0
neg.w D0
rts
* A0=window
LeftIt move.w wd_LeftEdge(A0),D0
neg.w D0
rts
HandlerSize = *-IHS
*====================== Input-handler end ===========================
*====================== Data-definition start =======================
rStart
rLong CLen
rAPtr CName
rAPtr PProcess
rAPtr WBMsg
rAPtr DosBase
rAPtr IntBase
rAPtr IconBase
rAPtr DiskObj
rAPtr HPort
rStorage IReq,IOSTD_SIZE
rStorage IPort,MP_SIZE
rAPtr HMem
rEnd
DosName dc.b 'dos.library',0
IntName dc.b 'intuition.library',0
IconName dc.b 'icon.library',0
InputName dc.b 'input.device',0
FileTxt dc.b 'FILE',0
END
--- InputEvent.ie_Class ---
IECLASS_NULL 0x00 A NOP input event
IECLASS_RAWKEY 0x01 A raw keycode from the keyboard device
IECLASS_RAWMOUSE 0x02 The raw mouse report from the game port device
IECLASS_EVENT 0x03 A private console event
IECLASS_POINTERPOS 0x04 A Pointer Position report
IECLASS_TIMER 0x06 A timer event
IECLASS_GADGETDOWN 0x07 select button pressed down over a Gadget (address in ie_EventAddress)
IECLASS_GADGETUP 0x08 select button released over the same Gadget (address in ie_EventAddress)
IECLASS_REQUESTER 0x09 some Requester activity has taken place. See Codes REQCLEAR and REQSET
IECLASS_MENULIST 0x0A this is a Menu Number transmission (Menu number is in ie_Code)
IECLASS_CLOSEWINDOW 0x0B User has selected the active Window's Close Gadget
IECLASS_SIZEWINDOW 0x0C this Window has a new size
IECLASS_REFRESHWINDOW 0x0D the Window pointed to by ie_EventAddress needs to be refreshed
IECLASS_NEWPREFS 0x0E new preferences are available
IECLASS_DISKREMOVED 0x0F the disk has been removed
IECLASS_DISKINSERTED 0x10 the disk has been inserted
IECLASS_ACTIVEWINDOW 0x11 the window is about to be made active
IECLASS_INACTIVEWINDOW 0x12 the window is about to be made inactive
IECLASS_MAX 0x12 the last class
--- InputEvent.ie_Code ---
IECLASS_RAWKEY
IECODE_UP_PREFIX 0x80
IECODE_KEY_CODE_FIRST 0x00
IECODE_KEY_CODE_LAST 0x77
IECODE_COMM_CODE_FIRST 0x78
IECODE_COMM_CODE_LAST 0x7F
IECLASS_ANSI
IECODE_C0_FIRST 0x00
IECODE_C0_LAST 0x1F
IECODE_ASCII_FIRST 0x20
IECODE_ASCII_LAST 0x7E
IECODE_ASCII_DEL 0x7F
IECODE_C1_FIRST 0x80
IECODE_C1_LAST 0x9F
IECODE_LATIN1_FIRST 0xA0
IECODE_LATIN1_LAST 0xFF
IECLASS_RAWMOUSE
IECODE_LBUTTON 0x68 also uses IECODE_UP_PREFIX
IECODE_RBUTTON 0x69
IECODE_MBUTTON 0x6A
IECODE_NOBUTTON 0xFF
IECLASS_EVENT
IECODE_NEWACTIVE 0x01 active input window changed
IECLASS_REQUESTER Codes
REQSET is broadcast when the first Requester (not subsequent ones) opens
in the Window
IECODE_REQSET 0x01
REQCLEAR is broadcast when the last Requester clears out of the Window
IECODE_REQCLEAR 0x00
--- InputEvent.ie_Qualifier ---
IEQUALIFIER_LSHIFT 0x0001
IEQUALIFIER_RSHIFT 0x0002
IEQUALIFIER_CAPSLOCK 0x0004
IEQUALIFIER_CONTROL 0x0008
IEQUALIFIER_LALT 0x0010
IEQUALIFIER_RALT 0x0020
IEQUALIFIER_LCOMMAND 0x0040
IEQUALIFIER_RCOMMAND 0x0080
IEQUALIFIER_NUMERICPAD 0x0100
IEQUALIFIER_REPEAT 0x0200
IEQUALIFIER_INTERRUPT 0x0400
IEQUALIFIER_MULTIBROADCAST 0x0800
IEQUALIFIER_MIDBUTTON 0x1000
IEQUALIFIER_RBUTTON 0x2000
IEQUALIFIER_LEFTBUTTON 0x4000
IEQUALIFIER_RELATIVEMOUSE 0x8000
IEQUALIFIERB_LSHIFT 0
IEQUALIFIERB_RSHIFT 1
IEQUALIFIERB_CAPSLOCK 2
IEQUALIFIERB_CONTROL 3
IEQUALIFIERB_LALT 4
IEQUALIFIERB_RALT 5
IEQUALIFIERB_LCOMMAND 6
IEQUALIFIERB_RCOMMAND 7
IEQUALIFIERB_NUMERICPAD 8
IEQUALIFIERB_REPEAT 9
IEQUALIFIERB_INTERRUPT 10
IEQUALIFIERB_MULTIBROADCAST 11
IEQUALIFIERB_MIDBUTTON 12
IEQUALIFIERB_RBUTTON 13
IEQUALIFIERB_LEFTBUTTON 14
IEQUALIFIERB_RELATIVEMOUSE 15
struct InputEvent
{
struct InputEvent *ie_NextEvent ;the chronologically next event
UBYTE ie_Class ;the input event class
UBYTE ie_SubClass ;optional subclass of the class
UWORD ie_Code ;the input event code
UWORD ie_Qualifier ;qualifiers in effect for the event
union
{
struct
{
WORD ie_x ;the pointer position for the event
WORD ie_y
} ie_xy
APTR ie_addr
} ie_position
struct timeval ie_TimeStamp ;the system tick at the event
};
ie_X =ie_position.ie_xy.ie_x
ie_Y =ie_position.ie_xy.ie_y
ie_EventAddress =ie_position.ie_addr