* 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