Mail Archives: djgpp/1996/04/26/21:35:17
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 <time.h>
#include <stdlib.h>
#include <bios.h>
#include <dpmi.h>
#include <conio.h>
#include <pc.h>
#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.
- Raw text -