From: "A.Appleyard" To: DJGPP AT SUN DOT SOE DOT CLARKSON DOT EDU Date: Fri, 20 Jan 1995 14:26:06 GMT Subject: An unexpected cure for a bug With help from Eli Zaretski I have got a Gnu C program (a text editor) to define a mouse handler interrupt routine (event()), by this instruction:- ... Mouse Jerry; ... Jerry.settrap(0x7f,&event); But there was a bug: the instruction `char events=R->x.ax;' in event() hereinunder, which gets the type of mouse event that caused the interrupt, always got 1 = "mouse moved" even if the mouse event was a button event. But when I replaced that instruction by `char events; events=R->x.ax;' the bug vanished and my program ran OK. I suspect that (the way djgpp compiles (initializing a variable as it is declared)) does something that the interrupt routine calling mechanism doesn't like. ............................................ #include #include #define Regs _go32_dpmi_registers /*-----*/ class Mouse {public: int x,y; char nbuttons,buttons,visible,handlerInstalled,mc; void show(); void hide(); void read(); void move(int X,int Y); void ymove(int X,int Y); void setup(); void settrap(uns int,void (*func)(Regs *)); inline Mouse(){}; ~Mouse();}; /*-----*/ /* Simulate a software interrupt from protected mode. Like int86() but calls DPMI services and so doesn't need DOS extender, only a DPMI server. */ int int86dpmi(int intno) {REGS r,s; Regs S; S=R; S.x.ss=S.x.sp=0; /* DPMI server is to provide stack for interrupt call */ S.x.flags=0; /* he likeliest forgot to zero the flags */ /* I replaced the call of _go32_dpmi_simulate_int() by a copy of its body here*/ r.h.bl=intno; r.h.bh=0; r.x.cx=0; r.x.di=(int)&S; if(intno==0x21 && S.x.ax==0x4b00) { /* call a child process */ r.x.ax=0xff0a; int86(0x21,&r,&s);} else {r.x.ax=0x0300; int86(0x31,&r,&s);} R=S; return R.d.eax;} /*-----*/ Regs cb_regs; static _go32_dpmi_seginfo cb_info; /* for callback */ /*-----*/ void event(Regs*R){short x,y,dx=R->x.si,dy=R->x.di; char events=R->x.ax; Jerry.buttons=R->x.bx; x=Jerry.x=R->x.cx/8; y=Jerry.y=R->x.dx/8; if(events&1&Jerry.mc) inject(252,0); /* move */ if(events&2) inject(255,0); if(events&0x20) inject(254,0); if(events&8) inject(253,0);} /* inject = put a char into the keyboard buffer (int16h/AX=5) */ /*-----*/ void Mouse::settrap(uns int mask,void (*func)(Regs *)) {REGS r; /* This is tricky in protected-mode. We must allocate a real-mode wrapper function which will be called by the mouse driver, and which in turn will switch to protected-mode and call our protected-mode handler function. */ if(!Jerry.nbuttons) return; if(!func) {Jerry.handlerInstalled=0; /* remove handler */ _go32_dpmi_free_real_mode_callback(&cb_info); R.x.dx=R.x.es=0;} else { /* Allocate real-mode call-back. Find real-mode address of handler */ cb_info.pm_offset=(uns long)func; Jerry.handlerInstalled=1; if(_go32_dpmi_allocate_real_mode_callback_retf(&cb_info,&cb_regs)) return; R.x.dx=cb_info.rm_offset; R.x.es=cb_info.rm_segment;} R.x.ax=12; R.x.cx=mask; int86dpmi(0x33);}