[comp.sys.amiga.tech] An Input handler problem

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 =============================================