www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/04/26/21:35:17

Xref: news2.mv.net comp.os.msdos.djgpp:3179
Newsgroups: comp.os.msdos.djgpp
From: Robert Jaycocks <r DOT jaycocks1 AT lut DOT ac DOT uk>
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
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 <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 -


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