Xref: news2.mv.net comp.os.msdos.djgpp:3179 Newsgroups: comp.os.msdos.djgpp From: Robert Jaycocks Subject: Re: mouse driver Sender: usenet AT lut DOT ac DOT uk (Usenet-News) Message-ID: <3180D447.555@lut.ac.uk> Date: Fri, 26 Apr 1996 13:48:55 GMT Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii References: <199604231338 DOT JAA15844 AT delorie DOT com> <317E2AD1 DOT 7DDA AT Mathematik DOT tu-chemnitz DOT de> Mime-Version: 1.0 Organization: LUT Lines: 283 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Robert Hoehne wrote: > > Martynas Kunigelis wrote: > > > > I really like to work in 132x30 text mode, and I was glad EMACS supported > > it. But the mouse... The idiot driver still thinks screen width is 80, so > > I'm also interested in it for use with RHIDE. I tried the same things > with int 33h calls, but no success. In my opinion, there must be written > a own mouse driver. > > Robert > -- > ***************************************************************** > * Robert Hoehne, Fakultaet fuer Mathematik, TU-Chemnitz-Zwickau * > * Post: Am Berg 3, D-09573 Dittmannsdorf * > * e-Mail: Robert DOT Hoehne AT Mathematik DOT TU-Chemnitz DOT DE * > * WWW: http://www.tu-chemnitz.de/~rho * > *****************************************************************The only way I managed to get mouse support in SVGA text modes (such as 132x50) was to write my own mouse routines. I prevented the mouse driver from displaying the mouse, then called DrawMouseCursor (my own routine) to display the cursor. When the mouse was moved, I repositioned the mouse on the screen. This meant I had to undisplay the cursor every time I updated the particular area of the screen where the cursor was, and then redisplay the cursor afterwards. Its a similar method when required to display a mouse on a graphics screen, since the standard mouse driver does not support graphics either. One could probably use interrupts to call your own routine every time the mouse position and status is altered. Unfortunely, I think this can cause problems. I found the program would crash when I moved the mouse, and the program was loading a file (ie a DOS interrupt was being called.) This meant I had to turn the mouse off when loading a file from disk. This was using the GRX library to display the mouse in a graphics mode. I did not need to use an interrupt method for the text based code. The following is my mouse.c file: /**********************************************************************//* */ /* mouse.c - Contains the mouse code. */ /* */ /* By Robert Jaycocks (c) 1994-96 */ /* */ /**********************************************************************/ #include "proto.h" #include "mouse.h" #include #include #include #include #include #include #ifdef __GNUC__ # define clock() rawclock() # undef CLOCKS_PER_SEC # define CLOCKS_PER_SEC 18.2 #endif static struct { WORD ax,bx,cx,dx; boolean Mouse; int mx,my; } MouseRegs; static void MouseInterrupt( WORD ax ) { __dpmi_regs r; r.x.ax = ax; r.x.bx = MouseRegs.bx; r.x.cx = MouseRegs.cx; r.x.dx = MouseRegs.dx; __dpmi_int(0x33,&r); MouseRegs.ax = r.x.ax; MouseRegs.bx = r.x.bx; MouseRegs.cx = r.x.cx; MouseRegs.dx = r.x.dx; } /* end MouseInterrupt */ void DrawMouseCursor( void ) { char Screen[2]; if (MouseRegs.Mouse) { gettext(MouseRegs.mx+1,MouseRegs.my+1, MouseRegs.mx+1,MouseRegs.my+1, Screen); Screen[1]^=0x7f; /* reverse the attribute. */ puttext(MouseRegs.mx+1,MouseRegs.my+1, MouseRegs.mx+1,MouseRegs.my+1, Screen); } /* endif */ } /* end DrawMouseCursor */ void GetCurrentEventStatus(int Flags, MouseEvent *e) { e->flags = 0; if (MouseRegs.Mouse) { for (; ; ) { if (kbhit()) { e->flags |= M_KEYPRESS; e->key = getkey(); } /* endif */ MouseInterrupt(3); if (MouseRegs.bx & 1) e->flags |= M_LEFT; if (MouseRegs.bx & 2) e->flags |= M_RIGHT; /* Convert to screen co-ordinates. */ e->x = MouseRegs.cx/8; e->y = MouseRegs.dx/8; if ((e->x != MouseRegs.mx) || (e->y != MouseRegs.my)) { /* Mouse moved */ e->flags |= M_MOTION; DrawMouseCursor(); MouseRegs.mx = e->x; MouseRegs.my = e->y; DrawMouseCursor(); } /* endif */ if (e->flags & M_KEYPRESS) break; if (e->flags & M_BUTTON) break; if(Flags) break; } /* endfor */ } else { if (kbhit()) { e->flags |= M_KEYPRESS; e->key = getkey(); } /* endif */ } /* endif */ e->time = clock(); e->kbstat = bioskey(2); } /* end GetCurrentEventStatus */ void InitMouse( void ) { static boolean MouseInitialised = FALSE; if(fi.UseMouse == FALSE) { MouseInitialised = TRUE; MouseRegs.Mouse = 0; return; } /* endif */ if (MouseInitialised == FALSE) { MouseInitialised = TRUE; /* Initialize mouse */ MouseInterrupt(0); if ((MouseRegs.Mouse = MouseRegs.ax) != 0) { /* Set horizontal range */ MouseRegs.cx = 0; MouseRegs.dx = (fi.display.twidth-1)*8; MouseInterrupt(7); /* Set Vertical range */ MouseRegs.cx = 0; MouseRegs.dx = (fi.display.theight-1)*8; MouseInterrupt(8); /* Center mouse. */ MouseRegs.cx = fi.display.twidth*4; MouseRegs.dx = fi.display.theight*4; MouseInterrupt(4); /* Convert to screen co-ordinates. */ MouseRegs.mx = fi.display.twidth/2; MouseRegs.my = fi.display.theight/2; } /* endif */ } else if(MouseRegs.Mouse) { /* This code is needed. The libgrx library seem to alter */ /* these values. */ /* Set horizontal range */ MouseRegs.cx = 0; MouseRegs.dx = (fi.display.twidth-1)*8; MouseInterrupt(7); /* Set Vertical range */ MouseRegs.cx = 0; MouseRegs.dx = (fi.display.theight-1)*8; MouseInterrupt(8); } /* endif */ } /* end InitMouse */ void GetEvent(MouseEvent *e) { long Time; MouseEvent event; for (; ; ) { GetCurrentEventStatus(0, e); if (e->flags & M_BUTTON) { /* Deal with mouse. */ /* We wait until mouse button is released. */ do { GetCurrentEventStatus(1,&event); /* Check to see whether the mouse has moved. */ if (event.x != e->x || event.y != e->y) { /* If it has, return. */ e->flags |= M_MOVING; return; } /* endif */ } while (event.flags & M_BUTTON); /* Try for double click. If another click within 2 seconds, */ /* we assume a double click. Should probably allow the user */ /* to change the sensitivity to suit his/her needs. */ if ((event.time - e->time)/(CLOCKS_PER_SEC/10) <= 2) { Time = clock(); for (; ; ) { GetCurrentEventStatus(1,&event); if(event.flags & M_BUTTON) break; if((clock()-Time)/(CLOCKS_PER_SEC/10) > 1) break; } /* endfor */ if (event.flags & M_BUTTON) { Time = event.time; do { GetCurrentEventStatus(1,&event); } while (event.flags & M_BUTTON); if (event.x == e->x && event.y == e->y && ((event.time - Time)/(CLOCKS_PER_SEC/10) <= 2)) { /* Double clicked */ e->flags |= M_DOUBLE_CLICKED; } /* endif */ } /* endif */ } /* endif */ return; } else if(e->flags & M_KEYPRESS) return; } /* endfor */ } /* end GetEvent */ NOTES: fi.display.twidth contains the width of the TEXT screen, fi.display.theight constains the height. To use the routine, I just called InitMouse to initialise the Mouse Driver, and then GetEvent to obtain the current input event. This was either a keypress, or a mouse event. eg: MouseEvent event; InitMouse(); DrawMouseCursor(); /* Turns on cursor */ for ( ; ;) { GetEvent(&event); if (event & M_KEYPRESS) { DrawMouseCursor(); /* Turns off mouse cursor */ /* Deal with keyboard event */ DrawMouseCursor(); /* Turns on mouse cursor */ } /* endif */ } /* endfor */ Robert.