#include #include #include #include #include #include #include #include #include #define SIG_BREAK SIGBREAKF_CTRL_C #define SIG_NOTICE SIGBREAKF_CTRL_D #define SIG_ON SIGBREAKF_CTRL_E #define SIG_OFF SIGBREAKF_CTRL_F #define NUM_PATCHES (sizeof(PatchTable) / sizeof(struct PatchInfo)) #define JMP_ABS 0x4EF9 struct Wedge { UWORD Command; APTR Address; UWORD Pad; }; struct PatchInfo { APTR NewRoutine; LONG Offset; ULONG *Destination; }; struct WindowNode { struct MinNode Node; struct Window *Window; UWORD *Pointer; BYTE Height, Width; BYTE XOffset, YOffset; BYTE Off; }; extern ULONG __far LVOClearPointer, LVOSetPointer, LVOOpenWindow, LVOOpenWindowTagList, LVOCloseWindow; extern VOID __stdargs StackOldSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset); extern VOID NewSetPointer(VOID); APTR OldSetPointer; VOID (* __asm OldClearPointer)(register __a0 struct Window *,register __a6 struct IntuitionBase *); struct Window * (* __asm OldOpenWindowTagList)(register __a0 struct NewWindow *,register __a1 struct TagItem *,register __a6 struct IntuitionBase *); struct Window * (* __asm OldOpenWindow)(register __a0 struct NewWindow *,register __a6 struct IntuitionBase *); VOID (* __asm OldCloseWindow)(register __a0 struct Window *,register __a6 struct IntuitionBase *); LONG __saveds Main(VOID); VOID __regargs UpdateNode(struct WindowNode *Node,struct Window *Window); struct WindowNode * __regargs NewNode(struct Window *Window); VOID __saveds __stdargs BlankerAction(CxMsg *CxMessage,CxObj *CxObject); VOID ShutdownCx(VOID); BYTE SetupCx(VOID); VOID TurnOff(VOID); VOID TurnOn(VOID); VOID __stdargs __saveds StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset); VOID __asm __saveds NewClearPointer(register __a0 struct Window *Window); struct Window * __asm __saveds NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList); struct Window * __asm __saveds NewOpenWindow(register __a0 struct NewWindow *NewWindow); VOID __asm __saveds NewCloseWindow(register __a0 struct Window *Window); struct ExecBase *SysBase; struct IntuitionBase *IntuitionBase; struct Library *CxBase; struct Process *MainProcess; struct SignalSemaphore WindowSemaphore; struct List WindowList; ULONG UseCount = 0, BlankCount = 0; BYTE AllOff = FALSE; struct MsgPort *CxPort; CxObj *Broker; struct NewBroker NewBroker = { NB_VERSION, "MouseBlanker", "Mouse Pointer Blanker v1.0", "Mouse Pointer Blanker", NBU_UNIQUE, NULL, 0,NULL,0 }; struct PatchInfo PatchTable[] = { NewClearPointer, (LONG)&LVOClearPointer, (ULONG *)&OldClearPointer, NewSetPointer, (LONG)&LVOSetPointer, (ULONG *)&OldSetPointer, NewOpenWindowTagList, (LONG)&LVOOpenWindowTagList, (ULONG *)&OldOpenWindowTagList, NewOpenWindow, (LONG)&LVOOpenWindow, (ULONG *)&OldOpenWindow, NewCloseWindow, (LONG)&LVOCloseWindow, (ULONG *)&OldCloseWindow }; UWORD __chip BlankSprite[(2 + 1) * 2] = { 0x0000,0x0000, 0x0000,0x0000, 0x0000,0x0000 }; LONG __saveds Main() { LONG Result = RETURN_FAIL; SysBase = *(struct ExecBase **)4; MainProcess = (struct Process *)SysBase -> ThisTask; if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) { if(CxBase = OpenLibrary("commodities.library",37)) { if(SetupCx()) { struct Wedge *WedgeTable; if(WedgeTable = (struct Wedge *)AllocMem(sizeof(struct Wedge) * NUM_PATCHES,MEMF_ANY|MEMF_CLEAR)) { struct WindowNode *Node, *Next; ULONG IntuiLock, SignalSet; struct Screen *Screen; struct Window *Window; BYTE Terminated = FALSE; WORD i; Result = RETURN_OK; InitSemaphore(&WindowSemaphore); NewList(&WindowList); IntuiLock = LockIBase(NULL); Screen = IntuitionBase -> FirstScreen; while(Screen) { Window = Screen -> FirstWindow; while(Window) { NewNode(Window); Window = Window -> NextWindow; } Screen = Screen -> NextScreen; } Forbid(); UnlockIBase(IntuiLock); for(i = 0 ; i < NUM_PATCHES ; i++) { WedgeTable[i] . Command = JMP_ABS; WedgeTable[i] . Address = PatchTable[i] . NewRoutine; *PatchTable[i] . Destination = (ULONG)SetFunction((struct Library *)IntuitionBase,PatchTable[i] . Offset,(APTR)&WedgeTable[i]); } CacheClearU(); Permit(); while(!Terminated) { SignalSet = Wait(SIG_BREAK | SIG_ON | SIG_OFF); if(SignalSet & SIG_BREAK) Terminated = TRUE; if(SignalSet & SIG_ON) TurnOn(); if(SignalSet & SIG_OFF) TurnOff(); } Forbid(); for(i = 0 ; i < NUM_PATCHES ; i++) WedgeTable[i] . Address = (APTR)*PatchTable[i] . Destination; CacheClearU(); SetSignal(0,SIG_NOTICE); Permit(); while(UseCount > 0) Wait(SIG_NOTICE); TurnOn(); ObtainSemaphore(&WindowSemaphore); Node = (struct WindowNode *)WindowList . lh_Head; while(Next = (struct WindowNode *)Node -> Node . mln_Succ) { Remove((struct Node *)Node); FreeVec(Node); Node = Next; } ReleaseSemaphore(&WindowSemaphore); } ShutdownCx(); } } CloseLibrary((struct Library *)IntuitionBase); } return(Result); } VOID __regargs UpdateNode(struct WindowNode *Node,struct Window *Window) { Node -> Pointer = Window -> Pointer; Node -> Height = Window -> PtrHeight; Node -> Width = Window -> PtrWidth; Node -> XOffset = Window -> XOffset; Node -> YOffset = Window -> YOffset; } struct WindowNode * __regargs NewNode(struct Window *Window) { struct WindowNode *Node; if(Node = (struct WindowNode *)AllocVec(sizeof(struct WindowNode),MEMF_PUBLIC | MEMF_CLEAR)) { Node -> Window = Window; UpdateNode(Node,Window); AddTail(&WindowList,(struct Node *)Node); } return(Node); } struct WindowNode * __regargs FindWindow(struct Window *Window) { struct WindowNode *Node, *Next; Node = (struct WindowNode *)WindowList . lh_Head; while(Next = (struct WindowNode *)Node -> Node . mln_Succ) { if(Window == Node -> Window) return(Node); Node = Next; } return(NULL); } VOID __saveds __stdargs BlankerAction(CxMsg *CxMessage,CxObj *CxObject) { struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage); switch(Event -> ie_Class) { case IECLASS_TIMER: if(BlankCount++ >= 50) { BlankCount = 0; Signal(MainProcess,SIG_OFF); } break; case IECLASS_RAWKEY: if(!(Event -> ie_Code & IECODE_UP_PREFIX)) Signal(MainProcess,SIG_OFF); break; case IECLASS_NEWPOINTERPOS: case IECLASS_POINTERPOS: case IECLASS_RAWMOUSE: Signal(MainProcess,SIG_ON); break; default: break; } } VOID ShutdownCx() { if(CxPort) { struct Message *Message; if(Broker) DeleteCxObjAll(Broker); RemPort(CxPort); while(Message = GetMsg(CxPort)) ReplyMsg(Message); DeleteMsgPort(CxPort); CxPort = NULL; Broker = NULL; } } BYTE SetupCx() { ShutdownCx(); if(CxPort = CreateMsgPort()) { CxPort -> mp_Node . ln_Name = NewBroker . nb_Name; AddPort(CxPort); NewBroker . nb_Port = CxPort; NewBroker . nb_Pri = 0; if(Broker = CxBroker(&NewBroker,NULL)) { CxObj *ObjectList; ObjectList = CxCustom(BlankerAction,NULL); if(!CxObjError(ObjectList)) { AttachCxObj(Broker,ObjectList); if(!CxObjError(Broker)) { ActivateCxObj(Broker,TRUE); return(TRUE); } } } } ShutdownCx(); return(FALSE); } VOID TurnOff() { ObtainSemaphore(&WindowSemaphore); if(!AllOff) { struct WindowNode *Node, *Next; Node = (struct WindowNode *)WindowList . lh_Head; while(Next = (struct WindowNode *)Node -> Node . mln_Succ) { if(!Node -> Off) { UpdateNode(Node,Node -> Window); StackOldSetPointer(Node -> Window,BlankSprite,1,16,0,0); Node -> Off = TRUE; } Node = Next; } AllOff = TRUE; } ReleaseSemaphore(&WindowSemaphore); } VOID TurnOn() { struct WindowNode *Node, *Next; ObtainSemaphore(&WindowSemaphore); AllOff = FALSE; BlankCount = 0; Node = (struct WindowNode *)WindowList . lh_Head; while(Next = (struct WindowNode *)Node -> Node . mln_Succ) { if(Node -> Off) { if(Node -> Pointer) StackOldSetPointer(Node -> Window,Node -> Pointer,Node -> Height,Node -> Width,Node -> XOffset,Node -> YOffset); else OldClearPointer(Node -> Window,IntuitionBase); Node -> Off = FALSE; } Node = Next; } ReleaseSemaphore(&WindowSemaphore); } VOID __asm __saveds NewClearPointer(register __a0 struct Window *Window) { struct WindowNode *Node; ObtainSemaphore(&WindowSemaphore); UseCount++; if(Node = FindWindow(Window)) { if(!AllOff) { OldClearPointer(Window,IntuitionBase); Node -> Off = FALSE; } else Node -> Off = TRUE; Node -> Pointer = NULL; } else OldClearPointer(Window,IntuitionBase); UseCount--; Signal(MainProcess,SIG_NOTICE); ReleaseSemaphore(&WindowSemaphore); } VOID __stdargs __saveds StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset) { struct WindowNode *Node; ObtainSemaphore(&WindowSemaphore); UseCount++; if(Node = FindWindow(Window)) { if(!AllOff) { StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset); Node -> Off = FALSE; } else Node -> Off = TRUE; Node -> Pointer = Pointer; Node -> Height = Height; Node -> Width = Width; Node -> XOffset = XOffset; Node -> YOffset = YOffset; } else StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset); UseCount--; Signal(MainProcess,SIG_NOTICE); ReleaseSemaphore(&WindowSemaphore); } struct Window * __asm __saveds NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList) { struct Window *Window; ULONG Signals; ObtainSemaphore(&WindowSemaphore); UseCount++; if(Window = OldOpenWindowTagList(NewWindow,TagList,IntuitionBase)) { NewNode(Window); Signals = SIG_NOTICE | SIG_ON; } else Signals = SIG_NOTICE; UseCount--; Signal(MainProcess,Signals); ReleaseSemaphore(&WindowSemaphore); return(Window); } struct Window * __asm __saveds NewOpenWindow(register __a0 struct NewWindow *NewWindow) { struct Window *Window; ULONG Signals; ObtainSemaphore(&WindowSemaphore); UseCount++; if(Window = OldOpenWindow(NewWindow,IntuitionBase)) { NewNode(Window); Signals = SIG_NOTICE | SIG_ON; } else Signals = SIG_NOTICE; UseCount--; Signal(MainProcess,Signals); ReleaseSemaphore(&WindowSemaphore); return(Window); } VOID __asm __saveds NewCloseWindow(register __a0 struct Window *Window) { struct WindowNode *Node; ObtainSemaphore(&WindowSemaphore); UseCount++; if(Node = FindWindow(Window)) { Remove((struct Node *)Node); FreeVec(Node); } OldCloseWindow(Window,IntuitionBase); UseCount--; Signal(MainProcess,SIG_NOTICE); ReleaseSemaphore(&WindowSemaphore); }