* PWkeys * 1991 by Preben Nielsen * * *HISTORY * Made with Hisoft V2.12 * * V1.0 20-Apr-91: This is first release. I made it over a year ago * V1.1 06-May-91: Corrected a bug that appeared when trying to activate * next/previous window when none was active * 07-May-91: Added 'Refresh Window', 'Minimize Window' and * 'Maximize Window'. * 08-May-91: Added 'Sub Bitplane' and 'Add BitPlane' and * 'Toggle Input-Lock'. * 09-May-91: Added screen-blanking to 'Toggle Input-Lock'. * 10-May-91: Added mouse-acceleration and sunmouse. * 14-May-91: Added automatic and persistent screen-blanking. * 15-May-91: Added automatic and persistent mouse-blanking. * V2.0 18-May-91: Now I test for key-releases (saves time). * 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/dos.i" include "libraries/dosextens.i" include "libraries/dos_lib.i" include "graphics/gfxbase.i" include "graphics/clip.i" include "graphics/layers_lib.i" include "graphics/graphics_lib.i" include "intuition/intuitionbase.i" include "intuition/intuition_lib.i" include "Workbench/startup.i" include "Workbench/workbench.i" include "Workbench/icon_lib.i" include "hardware/custom.i" include "hardware/dmabits.i" include "PWkeys.i" V_EHB =$80 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 PushS MACRO move.l \1,-(SP) ENDM PopS MACRO move.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 ON_DISPLAY MACRO move.w #BITSET|DMAF_RASTER,$DFF000+dmacon ENDM OFF_DISPLAY MACRO move.w #BITCLR|DMAF_RASTER,$DFF000+dmacon ENDM TEST_DISPLAY MACRO btst #DMAB_RASTER-8,$DFF000+dmaconr 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+ihs_PortName(PC),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 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 PWkeys_CON_Msg 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-D2/A0-A3/A6 moveq #0,D2 Call GetKeys beq 2$ Prepare Exec_Call lea Entry(PC),A0 CallLib AllocEntry move.l D0,MEntry(DB) bmi.S 2$ ; Is bit 31 set ? move.l D0,A3 move.l ML_ME+0*ME_SIZE(A3),A2 lea IHS(PC),A0 move.l A2,A1 move.w #HandlerSize,D0 Call MemCopy ; Copy handler lea ChipData(PC),A0 move.l ML_ME+1*ME_SIZE(A3),A1 move.w #ChipSize,D0 Call MemCopy ; Copy CHIP-data move.l A1,NewCopper-IHS(A2) lea MySprite-ChipData(A1),A1 move.l A1,NewSprite-IHS(A2) move.b PWkPri(PC),ihs_Interrupt+LN_PRI(A2) ; HandlerBlock.HInterrupt.is_Node.ln_Pri = PRI; lea HandlerCode-IHS(A2),A0 move.l A0,ihs_Interrupt+IS_CODE(A2) ; HandlerBlock.HInterrupt.is_Code = Handler lea PWkVersionID-IHS(A2),A0 move.l A0,ihs_Interrupt+IS_DATA(A2) ; HandlerBlock.HInterrupt.is_Data = KeyDefines; move.w #HStartFlags,ihs_Flags(A2) move.l A3,ihs_MemEntry(A2) lea LayerName(PC),A1 ; Libraries won't get closed CallLib OldOpenLibrary move.l D0,LAYERbase-IHS(A2) beq.S 2$ lea GfxName(PC),A1 CallLib OldOpenLibrary move.l D0,GFXbase-IHS(A2) beq.S 2$ lea IntName(PC),A1 CallLib OldOpenLibrary move.l D0,INTUIbase-IHS(A2) beq.S 2$ move.l A2,D2 2$ move.l D2,D0 Pop D1-D2/A0-A3/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 MEntry(DB),D0 bmi.S 1$ ; Is bit 31 set ? move.l D0,A0 Prepare Exec_Call CallLib FreeEntry 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$ move.l ihs_MemEntry(A0),A0 Prepare Exec_Call CallLib FreeEntry 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 TBuf(DB),A0 move.l A0,D2 move.l #pw_SIZE,D3 CallLib Read cmp.l D0,D3 bne.S 1$ lea TBuf(DB),A0 movem.l pw_ID(A0),D0-D1 movem.l PWkVersionID(PC),D2-D3 cmp.l D0,D2 bne.S 1$ cmp.l D1,D3 bne.S 1$ lea PWkVersionID(PC),A1 move.l #pw_SIZE,D0 Call MemCopy moveq #1,rtsValue 1$ move.l D4,D1 CallLib Close 2$ move.l rtsValue,D0 Pop D1-D7/A0-A6 rts * »»»»»»»»»»»»»»»»»»»»»» Data-definition start ««««««««««««««««««««««« rStart rLong CLen rAPtr CName rAPtr PProcess rAPtr WBMsg rAPtr DosBase rAPtr IconBase rAPtr DiskObj rAPtr HPort rAPtr MEntry rStorage IReq,IOSTD_SIZE rStorage IPort,MP_SIZE rStorage TBuf,pw_SIZE rEnd DosName dc.b 'dos.library',0 LayerName dc.b 'layers.library',0 GfxName dc.b 'graphics.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 EVEN Entry ds.b LN_SIZE dc.w 2 dc.l MEMF_CLEAR|MEMF_PUBLIC dc.l HandlerSize dc.l MEMF_CLEAR|MEMF_CHIP dc.l ChipSize * »»»»»»»»»»»»»»»»»»»»»» Data-definition end ««««««««««««««««««««««««« * »»»»»»»»»»»»»»»»»»»»»» Input-handler start ««««««««««««««««««««««««« HDisabled =0 HNoExtRemoval =1 HInputDisabled =2 HAccelMouse =3 HSunMouse =4 HScreenBlanked =5 HMouseBlanked =6 HStartFlags =0 * This is the handler-block IHS ihs_Start * Local variables Chain dc.l 0 OldSprite dc.l 0 NewSprite dc.l 0 NewCopper dc.l 0 INTUIbase dc.l 0 GFXbase dc.l 0 LAYERbase 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 PWkMouseAccel dc.b PWkeysMSpeed PWkMouseThresh dc.b PWkeysMThresh PWkMTimeout dc.l PWkeysMTimeout PWkSTimeout dc.l PWkeysSTimeout PWkMWaitTime dc.l 0 PWkSWaitTime dc.l 0 PWkHotKeys dc.w KeyFuncNumber * These defines are the default when no file is specified * Keep them sorted on 'Code|Qual' KeyDefines HotKey KP1,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_LEFT_BOTTOM HotKey KP2,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_BOTTOM HotKey KP3,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_RIGHT_BOTTOM HotKey KP4,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_LEFT HotKey KP5,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_CENTER HotKey KP6,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_RIGHT HotKey KP7,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_LEFT_TOP HotKey KP8,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_TOP HotKey KP9,LSHIFT|LAMIGA,LSHIFT|LAMIGA,W_TO_RIGHT_TOP HotKey BACKSPACE,LAMIGA|RAMIGA,LAMIGA|RAMIGA,TOGGLE_INPUTLOCK HotKey TAB,LSHIFT|LAMIGA,LSHIFT|LAMIGA,REFRESH_W HotKey DEL,LAMIGA|RAMIGA,LAMIGA|RAMIGA,TOGGLE_FASTMOUSE HotKey UPARROW,LAMIGA,SHIFT|AMIGA,FRONT_W_TO_BACK HotKey UPARROW,LSHIFT|LAMIGA,SHIFT|AMIGA,W_TO_BACK HotKey UPARROW,RSHIFT|RAMIGA,SHIFT|AMIGA,FRONT_S_TO_BACK HotKey DOWNARROW,LAMIGA,SHIFT|AMIGA,BACK_W_TO_FRONT HotKey DOWNARROW,LSHIFT|LAMIGA,SHIFT|AMIGA,W_TO_FRONT HotKey DOWNARROW,RSHIFT|RAMIGA,SHIFT|AMIGA,BACK_S_TO_FRONT HotKey RIGHTARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA,ACTIVATE_NEXT_W HotKey LEFTARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA,ACTIVATE_PREV_W HotKey F1,LSHIFT|LAMIGA,LSHIFT|LAMIGA,MINIMIZE_W HotKey F2,LSHIFT|LAMIGA,LSHIFT|LAMIGA,MAXIMIZE_W HotKey F9,RSHIFT|RAMIGA,RSHIFT|RAMIGA,SUB_BITPLANE HotKey F10,RSHIFT|RAMIGA,RSHIFT|RAMIGA,ADD_BITPLANE HotKey HELP,LAMIGA|RAMIGA,LAMIGA|RAMIGA,TOGGLE_SUNMOUSE * This is the end of the part coming from a file * This table below defines the connection between the * selected hotkey and the function to perform JmpEntry_SIZE =2 JmpEntry MACRO dc.w \1-JmpTable ENDM JmpTable JmpEntry WinToTop JmpEntry WinToBottom JmpEntry WinToLeft JmpEntry WinToRight JmpEntry WinToTL JmpEntry WinToBL JmpEntry WinToTR JmpEntry WinToBR JmpEntry WinToCenter JmpEntry WinToFront JmpEntry WinToBack JmpEntry BackWinToFront JmpEntry FrontWinToBack JmpEntry ActivatePrevWin JmpEntry ActivateNextWin JmpEntry MinimizeWin JmpEntry MaximizeWin JmpEntry RefreshWin JmpEntry BackScrToFront JmpEntry FrontScrToBack JmpEntry SubBitplane JmpEntry AddBitplane JmpEntry ToggleInputLock JmpEntry ToggleFastMouse JmpEntry ToggleSunMouse * 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. * Subroutines that uses other registers than the ones below, has * to save them first and restore them afterwards. SD EQUR D0 ; Scratch data register Accel EQUR D1 ; Acceleration Thresh EQUR D2 ; Threshold Min EQUR D1 ; For binary search Max EQUR D2 ; For binary search Num EQUR D3 ; For binary search TheKey EQUR D4 ; For binary search SA EQUR A0 ; Scratch address register Hkey EQUR A1 ; Hotkey PEvent EQUR A2 ; Previous Event Event EQUR A3 ; This Event StatusBits =IHS+ihs_Flags+1 Next =ie_NextEvent Class =ie_Class Code =ie_Code Qual =ie_Qualifier Seconds =ie_TimeStamp+TV_SECS Micros =ie_TimeStamp+TV_MICRO ButtonsQual =IEQUALIFIER_MIDBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_LEFTBUTTON * Call: A0 = List of InputEvents, A1 = HandlerData HandlerCode Push D1-D4/A0-A3 lea Chain(PC),PEvent move.l A0,Next(PEvent) btst #HDisabled,StatusBits(PC) ; Future feature bne NoMoreEvents ieLoop move.l Next(PEvent),Event move.l Event,SD beq NoMoreEvents * Process TIMER events CheckTimer cmpi.b #IECLASS_TIMER,Class(Event) bne.S CheckMouse CheckSBlanking btst #HScreenBlanked,StatusBits(PC) bne.S ForceSBlanking move.l PWkSWaitTime(PC),SD beq.S CheckMBlanking cmp.l Seconds(Event),SD bge.S CheckMBlanking ForceSBlanking TEST_DISPLAY ; Screen should be blanked ! beq NeverRemove Call BlankScreen ; But is isn't, so I blank it ! bra NeverRemove CheckMBlanking btst #HMouseBlanked,StatusBits(PC) bne.S ForceMBlanking move.l PWkMWaitTime(PC),SD beq NeverRemove cmp.l Seconds(Event),SD bge NeverRemove ForceMBlanking move.l GFXbase(PC),SA ; Mouse should be blanked ! move.l gb_copinit(SA),SA move.w copinit_sprstrtup+2(SA),SD swap SD move.w copinit_sprstrtup+6(SA),SD cmp.l NewSprite(PC),SD beq NeverRemove Call BlankMouse ; But it isn't, so I blank it now ! bra NeverRemove * Process RAWMOUSE events CheckMouse cmpi.b #IECLASS_RAWMOUSE,Class(Event) bne.S CheckKey btst #HInputDisabled,StatusBits(PC) bne Remove Call BreakSBlanking Call BreakMBlanking CheckFastMouse btst #HAccelMouse,StatusBits(PC) beq.S CheckSunMouse cmpi.w #IECODE_NOBUTTON,Code(Event) bne NeverRemove move.w Qual(Event),SD andi.w #ButtonsQual,SD bne NeverRemove moveq #0,Accel moveq #0,Thresh move.b PWkMouseAccel(PC),Accel move.b PWkMouseThresh(PC),Thresh move.w ie_X(Event),D0 Call CalcNewPos move.w D0,ie_X(Event) move.w ie_Y(Event),D0 Call CalcNewPos move.w D0,ie_Y(Event) CheckSunMouse btst #HSunMouse,StatusBits(PC) beq NeverRemove Call ActivateMWindow bra NeverRemove * Process RAWKey events CheckKey cmpi.b #IECLASS_RAWKEY,Class(Event) bne NeverRemove move.w Code(Event),TheKey ; Construct a 'Code|Qual' long-word btst #7,TheKey ; Is it a key-release ? bne DontRemoveKey swap TheKey ; It is a key-press ! 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 DontRemoveKey ; Didn't find a match move.w Num,SD lsl.w #3,SD ; HotKey_SIZE * Num lea KeyDefines(PC),Hkey add.w SD,Hkey move.l TheKey,SD and.l HotKey_Mask(Hkey),SD ; TheKey & KeyDefines[Num].HotKey_Mask cmp.l HotKey_ID(Hkey),SD ; 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 * Hkey = Hotkey Perform Push D0-D7/A0-A6 ; (TheKey & KeyDefines[Num].HotKey_Mask) = KeyDefines[Num].HotKey_ID moveq #0,D0 move.b HotKey_Func(Hkey),D0 ; KeyDefines[Num].HotKey_Func lsl.w #1,D0 ; JmpEntry_SIZE * KeyDefines[Num].HotKey_Func lea JmpTable(PC),A2 add.w 0(A2,D0.W),A2 btst #HInputDisabled,StatusBits(PC) beq.S 1$ lea ToggleInputLock(PC),A0 cmp.l A2,A0 bne.S 2$ 1$ Prepare Exec_Call CallLib Forbid move.l INTUIbase(PC),A6 ; Intuitionbase stays loaded jsr (A2) ; Jump to function Prepare Exec_Call CallLib Permit 2$ Pop D0-D7/A0-A6 RemoveKey btst #HInputDisabled,StatusBits(PC) bne.S Remove Call BreakSBlanking Remove move.l Next(Event),Next(PEvent); Remove event from chain and move on to next Event bra ieLoop DontRemoveKey btst #HInputDisabled,StatusBits(PC) bne.S Remove Call BreakSBlanking NeverRemove move.l Event,PEvent ; Just move on to next Event bra ieLoop NoMoreEvents Pop D1-D4/A0-A3 move.l Chain(PC),D0 ; Return (shortened ?) chain rts * »»»»»»»»»»» Misc functions called by the hotkey-functions «««««««««« * 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 * Destroys no registers 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 to check 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 * TopScreen() * Find the top screen * Return: D0 = Screen or NULL * Destroys D0-D1/A0-A1 TopScreen move.l ib_FirstScreen(A6),D0 rts * BottomScreen() * Find the bottom screen * Return: D0 = Screen or NULL * Destroys D0-D1/A0-A1 BottomScreen move.l ib_FirstScreen(A6),D0 beq.S 2$ 1$ move.l D0,A0 move.l sc_NextScreen(A0),D0 bne.S 1$ move.l A0,D0 2$ 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 * Destroys D0-D1/A0-A1 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 * Destroys D0-D1/A0-A1 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 * Destroys D0-D1/A0-A1 NextWindow moveq #0,D0 move.l wd_WLayer(A0),A1 1$ move.l lr_back(A1),D1 beq.S 2$ move.l D1,A1 move.l lr_Window(A1),D0 beq.S 1$ cmp.l A0,D0 beq.S 1$ 2$ 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 * Destroys D0-D1/A0-A1 PrevWindow moveq #0,D0 move.l wd_WLayer(A0),A1 1$ move.l lr_front(A1),D1 beq.S 2$ move.l D1,A1 move.l lr_Window(A1),D0 beq.S 1$ cmp.l A0,D0 beq.S 1$ 2$ tst.l D0 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) SizeWindow Call CheckWindow bne.S WinErr jmp _LVOSizeWindow(A6) WinErr rts * »»»»»»»»»»»»»»»»»»» Window manipulating functions «««««««««««««««««« * Move the active window in x/y directions * Destroys D0-D1/A0-A2 WinToTop lea TopIt(PC),A1 ; Window To Top lea DontMoveX(PC),A2 bra.S WindowMove WinToBottom lea BottomIt(PC),A1 ; Window To Bottom lea DontMoveX(PC),A2 bra.S WindowMove WinToLeft lea DontMoveY(PC),A1 ; Window To Left lea LeftIt(PC),A2 bra.S WindowMove WinToRight lea DontMoveY(PC),A1 ; Window To Right lea RightIt(PC),A2 bra.S WindowMove WinToTL lea TopIt(PC),A1 ; Window To Upper Left Corner lea LeftIt(PC),A2 bra.S WindowMove WinToTR lea TopIt(PC),A1 ; Window To Upper Right Corner lea RightIt(PC),A2 bra.S WindowMove WinToBL lea BottomIt(PC),A1 ; Window To Lower Left Corner lea LeftIt(PC),A2 bra.S WindowMove WinToBR lea BottomIt(PC),A1 ; Window To Lower Right Corner lea RightIt(PC),A2 bra.S WindowMove WinToCenter lea CenterHeight(PC),A1 ; Window To Center lea CenterWidth(PC),A2 * Call: A1 = Function to adjust position in y-direction * A2 = Function to adjust position in x-direction WindowMove move.l ib_ActiveWindow(A6),D0 beq.S 2$ move.l D0,A0 jsr (A1) move.w D0,D1 jsr (A2) bne.S 1$ tst.w D1 beq.S 2$ 1$ Call MoveWindow 2$ rts DontMoveX DontMoveY moveq #0,D0 rts * Call: 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 * Call: 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 * Call: 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 * Call: 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 * Call: A0 = Window TopIt move.w wd_TopEdge(A0),D0 neg.w D0 rts * Call: A0 = Window LeftIt move.w wd_LeftEdge(A0),D0 neg.w D0 rts * WinToFront() * Send the active window to the top of the list. * Destroys D0-D2/A0-A1 WinToFront move.l ib_ActiveScreen(A6),D0 beq.S 1$ move.l ib_ActiveWindow(A6),D2 beq.S 1$ move.l D0,A0 Call TopWindow cmp.l D0,D2 ; Same window ? (NOT NULL !) beq.S 1$ move.l D2,A0 Call WindowToFront 1$ rts * WinToBack() * Send the active window to the back of the list. * Destroys D0-D2/A0-A1 WinToBack move.l ib_ActiveScreen(A6),D0 beq.S 1$ move.l ib_ActiveWindow(A6),D2 beq.S 1$ move.l D0,A0 Call BottomWindow cmp.l D0,D2 ; Same window ? (NOT NULL !) beq.S 1$ move.l D2,A0 Call WindowToBack 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. * Destroys D0-D2/A0-A1 BackWinToFront move.l ib_ActiveScreen(A6),D0 beq.S 3$ move.l D0,A0 Call BottomWindow 1$ move.l D0,A0 tst.l D0 beq.S 3$ btst #0,wd_Flags+2(A0) ; BackDrop ? beq.S 2$ Call PrevWindow bra.S 1$ 2$ move.l A0,D2 Call WindowToFront move.l D2,A0 Call ActivateWindow 3$ rts * FrontWindowToBack() * Move the top window to the back, and activate the new top window. * Get the top window, send it top to the back, and activate the top * window. * Destroys D0-D2/A0-A1 FrontWinToBack move.l ib_ActiveScreen(A6),D2 beq.S 1$ move.l D2,A0 Call TopWindow beq.S 1$ move.l D0,A0 Call WindowToBack move.l D2,A0 Call TopWindow beq.S 1$ move.l D0,A0 Call ActivateWindow 1$ rts * ActivatePreviousWindow() * Get the window previous to the active window (if none, then get the * bottom window in the active screen), and activate that window. * Destroys D0-D2/A0-A1 ActivatePrevWin move.l ib_ActiveScreen(A6),D2 beq.S 3$ move.l ib_ActiveWindow(A6),D0 beq.S 1$ move.l D0,A0 Call PrevWindow bne.S 2$ move.l D2,A0 Call BottomWindow bra.S 2$ 1$ move.l D2,A0 move.l sc_FirstWindow(A0),D0 2$ beq.S 3$ move.l D0,A0 Call ActivateWindow 3$ rts * ActivateNextWindow() * Get the window below the active window and activate it. * Destroys D0-D2/A0-A1 ActivateNextWin move.l ib_ActiveScreen(A6),D2 beq.S 3$ move.l ib_ActiveWindow(A6),D0 beq.S 1$ move.l D0,A0 Call NextWindow bne.S 2$ move.l D2,A0 Call TopWindow bra.S 2$ 1$ move.l D2,A0 move.l sc_FirstWindow(A0),D0 2$ beq.S 3$ move.l D0,A0 Call ActivateWindow 3$ rts * Size the active window in x/y directions * Destroys D0-D1/A0-A2 MinimizeWin lea MinimizeY(PC),A1 lea MinimizeX(PC),A2 bra.S WindowSize MaximizeWin lea MaximizeY(PC),A1 lea MaximizeX(PC),A2 * Call: A1 = Function to adjust size in y-direction * A2 = Function to adjust size in x-direction WindowSize move.l ib_ActiveWindow(A6),D0 beq.S 2$ move.l D0,A0 move.l wd_Flags(A0),D0 andi.w #WINDOWSIZING,D0 beq.S 2$ jsr (A1) move.w D0,D1 jsr (A2) bne.S 1$ tst.w D1 beq.S 2$ 1$ Call SizeWindow 2$ rts * Call: A0 = Window MinimizeY move.w wd_MinHeight(A0),D0 sub.w wd_Height(A0),D0 rts * Call: A0 = Window MinimizeX move.w wd_MinWidth(A0),D0 sub.w wd_Width(A0),D0 rts * Call: A0 = Window MaximizeY move.l wd_WScreen(A0),A1 move.w sc_Height(A1),D0 sub.w wd_TopEdge(A0),D0 cmp.w #$FFFF,wd_MaxHeight(A0) beq.S 1$ cmp.w wd_MaxHeight(A0),D0 ble.S 1$ move.w wd_MaxHeight(A0),D0 1$ sub.w wd_Height(A0),D0 rts * Call: A0 = Window MaximizeX move.l wd_WScreen(A0),A1 move.w sc_Width(A1),D0 sub.w wd_LeftEdge(A0),D0 cmp.w #$FFFF,wd_MaxWidth(A0) beq.S 1$ cmp.w wd_MaxWidth(A0),D0 ble.S 1$ move.w wd_MaxWidth(A0),D0 1$ sub.w wd_Width(A0),D0 rts * Refresh the active windows border and gadgets * Destroys D0-D1/A0-A1 RefreshWin move.l ib_ActiveWindow(A6),D0 beq.S 1$ move.l D0,A0 CallLib RefreshWindowFrame 1$ rts * »»»»»»»»»»»»»»»»»»» Screen manipulating functions «««««««««««««««««« * BackScrToFront() * Bring the bottom-most screen to the top, and activate its top window. * While there is a screen following the active one, move the the next screen. * Bring that screen to the front and find its top window. If one was found, * activate the window. * Destroys D0-D1/A0-A1 BackScrToFront Call BottomScreen beq.S 1$ move.l D0,A0 PushS A0 Call ScreenToFront PopS A0 Call TopWindow beq.S 1$ move.l D0,A0 Call ActivateWindow 1$ rts * FrontScreenToBack() * Move the top screen to the back and activate the top window on the new * top screen. * Destroys D0-D1/A0-A1 FrontScrToBack Call TopScreen beq.S 1$ move.l D0,A0 PushS A0 Call ScreenToBack PopS A0 Call TopWindow beq.S 1$ move.l D0,A0 Call ActivateWindow 1$ rts Planes EQUR D2 Index EQUR D3 WScreen EQUR A2 WBitMap EQUR A3 WViewPort EQUR A4 LORESMAX =6 HIRESMAX =4 * Subtracts a bitplane from the active screen. * HAM-screens won't be touched. * EHB-screens won't be EHB-screens after this. * Destroys D0-D3/A0-A4 SubBitplane Call ASCommon beq.S 2$ move.w vp_Modes(WViewPort),D0 andi.w #V_HAM,D0 bne.S 2$ ; Don't touch HAM subq.w #1,Planes beq.S 2$ move.b Planes,bm_Depth(WBitMap) move.w Planes,Index mulu #4,Index move.l bm_Planes(WBitMap,Index),A0 clr.l bm_Planes(WBitMap,Index) move.w sc_Width(WScreen),D0 move.w sc_Height(WScreen),D1 move.l GFXbase(PC),A6 CallLib FreeRaster cmp.b #LORESMAX,Planes bge.S 1$ andi.w #~V_EHB,vp_Modes(a1) ; Clear EHB flag 1$ move.l INTUIbase(PC),A6 CallLib RemakeDisplay 2$ rts * Adds a bitplane to the active screen (if enough CHIP-memory). * HIRES-screens can get a maximum of 4 bitplanes. * LORES-screens can get a maximum of 6 bitplanes (6 bitplanes means EHB). * Destroys D0-D3/A0-A4 AddBitplane Call ASCommon beq.S 3$ move.w Planes,Index mulu #4,Index addq.w #1,Planes moveq #HIRESMAX,D1 move.w vp_Modes(WViewPort),D0 andi.w #V_HIRES,D0 ; HIRES ? bne.S 1$ moveq #LORESMAX,D1 1$ cmp.w D1,Planes bgt.S 3$ move.w sc_Width(WScreen),D0 move.w sc_Height(WScreen),D1 move.l GFXbase(PC),A6 CallLib AllocRaster move.l D0,bm_Planes(WBitMap,Index) beq.S 3$ move.l D0,A1 move.w bm_Rows(WBitMap),D0 swap D0 move.w bm_BytesPerRow(WBitMap),D0 moveq #2,D1 CallLib BltClear move.b Planes,bm_Depth(WBitMap) cmp.w #LORESMAX,Planes blt.S 2$ ori.w #V_EHB,vp_Modes(WViewPort) ; Depth >= 6 => set EHB flag ! 2$ move.l INTUIbase(PC),A6 CallLib RemakeDisplay 3$ rts ASCommon move.l ib_ActiveScreen(A6),D0 beq.S 1$ move.l D0,WScreen lea sc_BitMap(WScreen),WBitMap lea sc_ViewPort(WScreen),WViewPort moveq #0,Planes move.b bm_Depth(WBitMap),Planes 1$ rts * »»»»»»»»»»»»»»»»»»» Misc manipulating functions «««««««««««««««««««« * Enables/Disables RAWKEY/RAWMOUSE events * Destroys D0-D1/A0-A1 ToggleInputLock lea StatusBits(PC),A0 bchg #HInputDisabled,(A0) beq.S BlankScreen bra.S BreakSBlanking * Enables/Disables mouse-acceleration * Destroys D0-D1/A0-A1 ToggleFastMouse lea StatusBits(PC),A0 bchg #HAccelMouse,(A0) rts * Enables/Disables sun-mouse * Destroys D0-D1/A0-A1 ToggleSunMouse lea StatusBits(PC),A0 bchg #HSunMouse,(A0) rts * »»»»»»»»»»»»»»» Misc functions called by handler ««««««««««««««««««« * Blanks the screen by installing a temporary copper-list, which * ensures a black display, and then turning the raster-DMA off. BlankScreen Push D1-D7/A0-A2/A6 Prepare Exec_Call CallLib Forbid lea StatusBits(PC),A0 bset #HScreenBlanked,(A0) move.l GFXbase(PC),A6 move.l gb_ActiView(A6),A1 move.l v_LOFCprList(A1),A2 movem.w (A2),D2-D7 ; Save CprList (10 bytes) clr.l crl_Next(A2) move.l NewCopper(PC),crl_start(A2) CallLib LoadView ; Install a one-color copperlist OFF_DISPLAY movem.w D2-D7,(A2) ; Restore CprList (10 bytes) Prepare Exec_Call CallLib Permit Pop D1-D7/A0-A2/A6 rts * Sets new screen-blanking timeout and turns the raster-DMA * back on, if it is off. BreakSBlanking move.l PWkSTimeout(PC),D0 beq.S 1$ add.l Seconds(Event),D0 1$ lea PWkSWaitTime(PC),A0 move.l D0,(A0) lea StatusBits(PC),A0 bclr #HScreenBlanked,(A0) beq.S 2$ PushS A6 move.l GFXbase(PC),A6 move.l gb_ActiView(A6),A1 CallLib LoadView ON_DISPLAY PopS A6 2$ rts * Blanks the mouse by installing an invisible image for sprite 0 * in the copper-list BlankMouse PushS A6 Prepare Exec_Call CallLib Forbid move.l GFXbase(PC),A1 move.l gb_copinit(A1),A1 lea copinit_sprstrtup(A1),A1 cmp.w #$0120,(A1) bne.S 2$ cmp.w #$0122,4(A1) bne.S 2$ lea StatusBits(PC),A0 bset #HMouseBlanked,(A0) bne.S 1$ lea OldSprite(PC),A0 move.w 2(A1),(A0)+ move.w 6(A1),(A0) 1$ lea NewSprite(PC),A0 move.w (A0)+,2(A1) move.w (A0),6(A1) 2$ Prepare Exec_Call CallLib Permit PopS A6 rts * Sets new mouse-blanking timeout and restores the old * sprite 0 image, if the mouse is off. BreakMBlanking PushS A6 move.l PWkMTimeout(PC),D0 beq.S 1$ add.l Seconds(Event),D0 1$ lea PWkMWaitTime(PC),A0 move.l D0,(A0) lea StatusBits(PC),A0 bclr #HMouseBlanked,(A0) beq.S 2$ Prepare Exec_Call CallLib Forbid move.l GFXbase(PC),A1 move.l gb_copinit(A1),A1 move.w OldSprite+0(PC),copinit_sprstrtup+2(A1) move.w OldSprite+2(PC),copinit_sprstrtup+6(A1) Prepare Exec_Call CallLib Permit 2$ PopS A6 rts * Activate the window the mouse is over (if any, and if it is not * already active). ib_MouseY =ib_FirstScreen+8 ib_MouseX =ib_MouseY+2 ActivateMWindow Push D1-D2/A0-A2/A6 Prepare Exec_Call CallLib Forbid move.l INTUIbase(PC),A2 move.l ib_FirstScreen(A2),A1 ScrSLoop move.l A1,D0 beq.S DoneAMW ; Out of screens ? move.w ib_MouseX(A2),D0 move.w ib_MouseY(A2),D1 move.w sc_ViewPort+vp_Modes(A1),D2 btst #15,D2 bne.S WasHIRES asr.w #1,D0 WasHIRES btst #2,D2 bne.S WasLACE asr.w #1,D1 WasLACE sub.w sc_ViewPort+vp_DyOffset(A1),D1 bge.S FoundScr move.l sc_NextScreen(A1),A1 bra.S ScrSLoop FoundScr lea sc_LayerInfo(A1),A0 ; Mouse is on this screen move.l LAYERbase(PC),A6 CallLib WhichLayer tst.l D0 beq.S DoneAMW ; No layer ? move.l D0,A0 move.l lr_Window(A0),D0 beq.S DoneAMW ; No window ? move.l INTUIbase(PC),A6 cmp.l ib_ActiveWindow(A6),D0 beq.S DoneAMW move.l D0,A0 Call ActivateWindow DoneAMW Prepare Exec_Call CallLib Permit Pop D1-D2/A0-A2/A6 rts * Call: D0:16 = ie_X/ie_Y * Return: D0:16 = modified ie_X/ie_Y * Calculates new mouse position using acceleration and threshold. CalcNewPos tst.w D0 bge.S 2$ add.w Thresh,D0 bge.S 1$ mulu Accel,D0 1$ sub.w Thresh,D0 rts 2$ sub.w Thresh,D0 ble.S 3$ mulu Accel,D0 3$ add.w Thresh,D0 rts HandlerSize =*-IHS * The data below goes into CHIP memory ChipData MyCopperList dc.w $0180,$0000 ; Copperlist that ensures dc.w $FFFF,$FFFE ; a one-color display (black) MySprite dc.w $FE00,$FF00 ; Invisible sprite dc.w $0000,$0000 dc.w $0000,$0000 ChipSize =*-ChipData * »»»»»»»»»»»»»»»»»»»»»» Input-handler end ««««««««««««««««««««««««««« END * »»»»»»»»»»»»»»»»»»»»»»»»»» The End «««««««««««««««««««««««««««««««««