home *** CD-ROM | disk | FTP | other *** search
- * InputLock
- * By Preben Nielsen
- *
- * This program is intended as a help to Amiga-users who has cats
- * or other pets (or children) that messes with the Amiga as soon
- * as you leave it for a second.
- *
- * It installes an input-handler which lets you lock the keyboard
- * and mouse by pressing a few buttons (currently LALT-CTRL-'l').
- *
- * Once installed, the program only uses 190 bytes of memory. To
- * remove the handler simply run the program 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 11-Apr-91: First attempt. Works of course.
- * V1.1 19-May-91: Help, I just found out that my "TellInputDevice"
- * routine trashes memory-address 0 because it didn't
- * do a "NewList" on its Message-port. It didn't cause
- * any problems most of the time, but it has now been
- * cured.
-
- OPT O+
- OPT O1+ ; Tells when a branch could be optimised to short
- OPT i+ ; Tells when '#' is probably missing
-
- 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/dosextens.i"
- include "libraries/dos_lib.i"
-
- Prepare MACRO
- IFC '\1','Exec_Call'
- movea.l 4.W,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 InputLock,CODE
- InitProcess rAlloc ; Allocate memory for variables
- rClear ; Clear the memory
- Prepare Exec_Call
- suba.l A1,A1
- CallLib FindTask ; Find us
- move.l D0,PProcess(DB)
- movea.l D0,A2
- tst.l pr_CLI(A2)
- bne.S GetLibs
- 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
- GetLibs lea DosName(PC),A1
- CallLib OldOpenLibrary
- move.l D0,DosBase(DB)
- beq.S Error
-
- CallLib Forbid
- lea IHS(PC),A1
- lea ihs_PortName(A1),A1
- CallLib FindPort
- move.l D0,D2
- CallLib Permit
- move.l D2,D0 ; Does Forbid/Permit destroy scratch-registers ?
- 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),D2
- beq.S AllDone
- CallLib Forbid ; We were started from WB
- movea.l D2,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/InputLock',0
- Msg dc.b 10,$9B,'0;33m InputLock V1.1',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 MP_MSGLIST(A3),A0
- NEWLIST A0
- 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
- 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
- clr.l ihs_Interrupt+IS_DATA(A1) ; HandlerBlock.HInterrupt.is_Data = 0
- move.b #HPRI,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
-
-
- *====================== 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
-
- HPRI =127 ; Handler-priority
- HDisabled =0
- HNoExtRemoval =1 ; Future
-
- * This is the handler-block
- IHS ihs_Start <'InputLock V1.1 Port'>
- * Local variables
- Chain dc.l 0
- Status dc.w 0
- INPUTDISABLED =0
- * For each event in the event list:
- * If we were waiting for this event then process it.
- * When all the events have been checked, return the event list so that
- * others can do their things.
- PEvent EQUR A2 ; Previous Event
- Event EQUR A1 ; This Event
- Bits EQUR A0
-
- Next =ie_NextEvent
- Class =ie_Class
- Code =ie_Code
- Qual =ie_Qualifier
- * These are the qualifier-keys the input-handler waits for
- QUALIFIERS =IEQUALIFIER_LALT|IEQUALIFIER_CONTROL
- * These are the keys the input-handler acts on
- Toggle_Key =$28 ; 'l'
- * Call: A0 = List of InputEvents, A1 = HandlerData
- HandlerCode Push Bits/Event/PEvent
- move.w IHS+ihs_Flags(PC),D0
- btst #HDisabled,D0 ; Future feature
- bne.S NoMoreEvents
- lea Chain(PC),PEvent
- move.l A0,Next(PEvent)
- lea Status(PC),Bits
- ieLoop move.l Next(PEvent),Event
- move.l Event,D0
- beq.S NoMoreEvents
- cmpi.b #IECLASS_RAWMOUSE,Class(Event)
- beq.S CheckLock
- cmpi.b #IECLASS_RAWKEY,Class(Event)
- bne.S DontRemove
- move.w Qual(Event),D0
- andi.w #QUALIFIERS|IEQUALIFIER_REPEAT,D0
- cmpi.w #QUALIFIERS,D0
- bne.S CheckLock
- cmp.w #Toggle_Key,Code(Event)
- bne.S CheckLock
- bchg #INPUTDISABLED,(Bits)
- bra.S Remove
- CheckLock btst #INPUTDISABLED,(Bits)
- bne.S Remove
- * Just move on to next Event
- DontRemove move.l Event,PEvent
- bra.S ieLoop
- * Remove event from chain and move on to next Event
- Remove move.l Next(Event),Next(PEvent)
- bra.S ieLoop
- * Lets return
- NoMoreEvents Pop Bits/Event/PEvent
- move.l Chain(PC),D0 ; Return (shortened ?) chain
- rts
- HandlerSize = *-IHS
- *====================== Input-handler end ===========================
-
- *====================== Data-definition start =======================
- rStart
- rAPtr PProcess
- rAPtr WBMsg
- rAPtr DosBase
- rStorage IReq,IOSTD_SIZE
- rStorage IPort,MP_SIZE
- rAPtr HMem
- rEnd
-
- DosName dc.b 'dos.library',0
- InputName dc.b 'input.device',0
- END
-
-