delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/01/20/10:15:20

From: "A.Appleyard" <A DOT APPLEYARD AT fs2 DOT mt DOT umist DOT ac DOT uk>
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 <pc.h>
#include <dpmi.h>
#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);}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019