sutela@polaris.utu.fi (Kari Sutela) (08/05/90)
I have a problem with an input handler I have tried to make. The idea of the handler is to restrict the user's mouse movements so that he shouldn't be able to move above or to the left of some predetermined position. I have been able to make a handler which works to some degree (it doesn't guru or anything) but is a bit too restrictive on the mouse movements. One can't move up or left at all. Below is a complete example program which should exhibit the problem. It's for Manx C v. 5.0a. The problem seems to be that the values supplied with the data-pointer won't get updated within the loop in the handler code. Somehow they CAN be updated at the start of the handler code, though. Any help would be greatly appreciated, as I'm truly baffled. Kari Sutela sutela@polaris.utu.fi ==== cut here for handler.c ============================================= /* * handler.c * * Example input event interceptor program * * Should allow the user the mouse pointer provided that he doesn't move it * to the left or above the initial mouse position. Somehow this doesn't * work, though => one can't move the mouse left or up at all. * * (Initially was MREVS.C by Matthew Dillon, public domain.) Changes and * Manx C v. 5.0a enhancements by Kari Sutela. */ #include <exec/types.h> #include <exec/nodes.h> #include <exec/interrupts.h> #include <devices/inputevent.h> #include <devices/input.h> #include <libraries/dos.h> #include <functions.h> typedef struct InputEvent IE; typedef struct MsgPort PORT; typedef struct IOStdReq IOR; typedef struct Interrupt INT; typedef void (*FPTR)(); /* * Our handler function. Receives arguments in registers a0 and a1. */ IE *handler( IE *, WORD * ); #pragma regcall( handler(a0,a1) ) /* * An ugly global. In a real application one should use handnode.is_Data * instead. */ int hits = 0; extern int Enable_Abort; main() { IOR *ior; PORT *port; INT handnode; /* * Here we put the mouse pointer position information. Let's initialize * it here to demonstrate that the handler can indeed change the values. */ WORD pos[2] = {20,20}; Enable_Abort = 0; port = CreatePort( NULL, NULL ); ior = (IOR *) CreateExtIO( port, sizeof(IOR) ); handnode.is_Node.ln_Pri = 51; handnode.is_Code = (FPTR)handler; handnode.is_Data = (APTR) &pos[0]; if (OpenDevice("input.device", NULL, (struct IORequest *) ior, NULL)) { puts("unable to open input.device!"); goto failure; } printf( "hits = %u, pos[0] = %d, pos[1] = %d\n", hits, pos[0], pos[1] ); puts("adding"); ior->io_Command = IND_ADDHANDLER; ior->io_Data = (APTR) &handnode; ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; DoIO((struct IORequest *) ior); for (;;) { long mask = Wait((long)SIGBREAKF_CTRL_C); if (mask & SIGBREAKF_CTRL_C) break; } puts("removing"); printf( "hits = %u, pos[0] = %d, pos[1] = %d\n", hits, pos[0], pos[1] ); ior->io_Command = IND_REMHANDLER; ior->io_Data = (APTR)&handnode; ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; DoIO((struct IORequest *) ior); CloseDevice((struct IORequest *) ior); failure: DeletePort(port); DeleteExtIO((struct IORequest *) ior); } IE *handler( IE *Ev, WORD *data ) { register IE *ev; int_start(); /* * The current mouse location is the 'origin'. */ data[0] = data[1] = 0; for (ev = Ev; ev; ev = ev->ie_NextEvent) { if (ev->ie_Class == IECLASS_RAWMOUSE) { /* Would we move to the left of the initial position? */ if( data[0] + ev->ie_X < 0 ) { ev->ie_X = 0; hits++; } /* Would we move above the initial position? */ if( data[1] + ev->ie_Y < 0 ) { ev->ie_Y = 0; hits++; } /* HERE'S THE PROBLEM: * Let's update the current position. * Somehow this doesn't * seem to have any effect at all. ????? */ data[0] += ev->ie_X; data[1] += ev->ie_Y; } } int_end(); return(Ev); } ==== end of handler.c =============================================== ==== test runs ====================================================== Here are a couple of test runs. During the first one I tried to move the mouse left and up (hits reflects this properly). During the second I didn't move the mouse left or up at all (hits = 0 as it should) but nevertheless, pos[0] and pos[1] remain 0. I'm truly astonished. ; The first run. (The mysterious numbers are just my WShell-prompt). R(0);12:33:35-06.800> handler hits = 0, pos[0] = 20, pos[1] = 20 adding removing hits = 52, pos[0] = 0, pos[1] = 0 ; The second run. R(48);12:33:40-03.600> handler hits = 0, pos[0] = 20, pos[1] = 20 adding removing hits = 0, pos[0] = 0, pos[1] = 0 ===== end of test runs =================================================== Here's part of the assembly output by the v. 5.0a compiler (cc -so -at handler). I have casually inspected it but couldn't see any obvious bugs. I'm barely assembly-literate, so I can't trust myself too much on this. ==== handler.asm ======================================================= ;IE *handler( IE *Ev, WORD *data ) ;{ xdef _handler _handler: movem.l a2/a3/a6,-(sp) movem.l a0/a1,-(sp) move.l 0(sp),a6 move.l 4(sp),a3 ; register IE *ev; ; ; int_start(); jsr _int_start ; ; /* ; * The current mouse location is the 'origin'. ; */ ; data[0] = data[1] = 0; clr.w 2(a3) clr.w (a3) ; for (ev = Ev; ev; ev = ev->ie_NextEvent) { move.l a6,a2 bra .10009 .10008 ; if (ev->ie_Class == IECLASS_RAWMOUSE) { cmp.b #2,4(a2) bne .10010 ; /* Would we move to the left of the initial position? */ ; if( data[0] + ev->ie_X < 0 ) { move.w (a3),a0 move.w 10(a2),a1 add.l a1,a0 move.l a0,d0 bge .10011 ; ev->ie_X = 0; clr.w 10(a2) ; hits++; add.l #1,_hits ; } ; /* Would we move above the initial position? */ ; if( data[1] + ev->ie_Y < 0 ) { .10011 move.w 2(a3),a0 move.w 12(a2),a1 add.l a1,a0 move.l a0,d0 bge .10012 ; ev->ie_Y = 0; clr.w 12(a2) ; hits++; add.l #1,_hits ; } ; /* ; * let's update the current position. Somehow this doesn't ; * seem to have any effect at all. ????? ; */ ; data[0] += ev->ie_X; .10012 move.w 10(a2),d0 add.w d0,(a3) ; data[1] += ev->ie_Y; move.l a3,a0 add.l #2,a0 move.w 12(a2),d0 add.w d0,(a0) ; } ; } .10010 .10006 move.l (a2),a2 .10009 move.l a2,d0 bne .10008 .10007 ; ; int_end(); jsr _int_end ; return(Ev); move.l a6,d0 .5 add.w #8,sp movem.l (sp)+,a2/a3/a6 rts ; ;} ==== end of handler.asm =============================================