From: "A.Appleyard" To: DJGPP AT SUN DOT SOE DOT CLARKSON DOT EDU Date: Mon, 13 Mar 1995 13:18:05 GMT Subject: How I handle the mouse in Gnu C (P.S. Please does anyone out there know the email address of am email group re FLYING (aeroplanes and helicopters) (real, not toy))? .................................................................. People have asked about Gnu C mouse handling. With Leo Zaretski's help I got a Gnu C program to handle the mouse thus:- /*-----*/ #include class Mouse; /*-----*/ class mousestate {public: int x,y,xe,ye; char visible,mc,bd; inline mousestate(){}; void operator=(Mouse&);}; /*-----*/ class Mouse {public: int x,y,xe,ye,ldx,ldy,mdx,mdy,rdx,rdy; char nbuttons,buttons,visible,handlerInstalled,mc,bd; void show(); void hide(); void read(); void move(int Y,int X); inline Mouse(){}; void setup(); void operator=(mousestate&); void settrap(uns int,void (*func)(Regs *)); void range(int ye,int xe); ~Mouse();}; /*-----*/ Mouse Jerry; int oldmx,oldmy; enum{LB=1,MB=4,RB=2}; Regs R; /*-----*//* Put a char into DOS's input buffer. Returns 0 if fail */ int inject(int C){R.x.ax=0x500; R.x.cx=C<0?((-C)&0xff)<<8:((C&0xff)<<8)+(C&0xff); Int(0x16);return !(R.x.ax&1);} /*-----*/ void Mouse::show(){R.x.ax=1; Int(0x33); visible=1;}; void Mouse::hide(){R.x.ax=2; Int(0x33); visible=0;}; void Mouse::read(){R.x.ax=3; Int(0x33); x=R.x.cx>>3; y=R.x.dx>>3;}; void Mouse::move(int Y,int X){ R.x.ax=4; R.x.cx=X*8+4; R.x.dx=Y*8+4; Int(0x33); read();}; void Mouse::range(int YE,int XE){ R.x.ax=7; R.x.cx=0; R.x.dx=XE*8-1; Int(0x33); xe=XE; R.x.ax=8; R.x.cx=0; R.x.dx=YE*8-1; Int(0x33); ye=YE;} Mouse::~Mouse(){hide(); settrap(0,(void (*)(Regs *))(0));}; void Mouse::operator=(mousestate&m){move(m.x,m.y); if(m.visible) show(); else hide(); mc=m.mc; bd=m.bd; range(m.ye,m.xe);} /*-----*/ void mousestate::operator=(Mouse&m){ x=m.x; y=m.y; visible=m.visible; mc=m.mc; bd=m.bd; xe=m.xe; ye=m.ye;}; /*-----*/ /* 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 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);} /*-----*/ void event(Regs*R){char events; events=R->x.ax; Jerry.buttons=R->x.bx&7; Jerry.x=R->x.cx/8; Jerry.y=R->x.dx/8; if(events&1&Jerry.mc) inject(-mousemove); /* mouse moved */ #define J Jerry /* buttons pressed */ if(events&0x02) {if(J.bd) inject(-lbuttond); J.ldx=J.x; J.ldy=J.y;} if(events&0x20) {if(J.bd) inject(-mbuttond); J.mdx=J.x; J.mdy=J.y;} if(events&0x08) {if(J.bd) inject(-rbuttond); J.rdx=J.x; J.rdy=J.y;} if(events&0x04) inject(-lbutton); /* buttons released */ if(events&0x40) inject(-mbutton); if(events&0x10) inject(-rbutton);} #undef J /*-----*/ void Mouse::setup() {_go32_dpmi_seginfo info; /* Check if a mouse is installed. If it is, then somebody (the mouse driver) should have grabbed the 33h interrupt vector. */ buttons=nbuttons=handlerInstalled=visible=0; /* if(_go32_dpmi_get_real_mode_interrupt_vector(0x33,&info)) return; if(!info.rm_segment) if(!info.rm_offset) return; /* exit if no mouse driver */ R.x.ax=0; Int(0x33); /* Initialise mouse driver */ if(!(R.x.ax&0xffff)) return; /* no mouse found */ nbuttons=R.x.bx&0xff; move(0,0); mc=bd=0; hide(); range(gp_Cols,gp_Rows);} /*-----*/ main(){............ Jerry.setup(); Jerry.settrap(0x7f,&event);