From: webbs@CS.ColoState.EDU (Steven Webb (The walking glitch))
Newsgroups: comp.os.msdos.programmer
Subject: Some C code for mouse routines (no middle button though)
Date: 6 Oct 92 03:49:55 GMT
Distribution: usa
Organization: Colorado State University - Computer Science Dept.

--
	Here is some code given to my Computer Graphics class
	Origin unknown, but thanks to Mike Goss!

	The Middle button on my dexxa mouse isn't recognized though.

	This code should be pretty easily converted to ASM if
	necessary.

	I've implemented it, if there's any questions.
--

/*	mouse.h - interface to Microsoft Mouse and compatibles		*/

/*	define button numbers and masks		*/

#define MOUSE_L		0
#define MOUSE_R		1
#define MOUSE_M		2

#define MOUSE_LM	(1 << MOUSE_L)
#define MOUSE_RM	(1 << MOUSE_R)
#define MOUSE_MM	(1 << MOUSE_M)

/*	function interface definitions	*/

/*	mouse_reset - returns -1 if no mouse, otherwise, no. of buttons	*/

int mouse_reset( void );

/*	mouse_show_cursor - turns on the mouse cursor	*/

void mouse_show_cursor( void );

/*	mouse_hide_cursor - turns off the mouse cursor */

void mouse_hide_cursor( void );

/*	mouse_get_status - get position and button status	*/

void mouse_get_status(	short *buttons,
					short *x_pos,
					short *y_pos );

/*	mouse_set_cursor - set cursor position	*/

void mouse_set_cursor( short x_pos, short y_pos );

/*	mouse_get_press - get button press status	*/

void mouse_get_press(	short button,
				short *status,
				short *count,
				short *x_pos,
				short *y_pos );

/*	mouse_get_release - get button release status	*/

void mouse_get_release(	short button,
					short *status,
					short *count,
					short *x_pos,
					short *y_pos );

/*	mouse_set_x_limits - set cursor x direction travel limits	*/

void mouse_set_x_limits( short x_min, short x_max );

/*	mouse_set_y_limits - set cursor y direction travel limits	*/

void mouse_set_y_limits( short y_min, short y_max );

/*	mouse_set_cursor_image - set new cursor image	*/

void mouse_set_cursor_image(	short x_hot,
					short y_hot,
					short *image );

/*	mouse_set_text_cursor - set text cursor parameters	*/

#define MOUSE_TEXT_CURSOR_SOFTWARE	0
#define MOUSE_TEXT_CURSOR_HARDWARE	1

void mouse_set_text_cursor(	short type, short start, short stop );

/*	mouse_read_counters - read raw movement counts since last request  */

void mouse_read_counters( short *x_count, short *y_count );

/*	mouse_set_speed - set number of number of mickeys per 8 pixels	*/

void mouse_set_speed( short x_ratio, short y_ratio );

/*	mouse_set_double - set mouse speed at which cursor travel doubles  */

void mouse_set_double( short speed );

--------------------------------------------CUT------------------------------------

/*	mouse.c - Microsoft Mouse interface for Microsoft C and Turbo C. */

#include <dos.h>

#include "mouse.h"

#define MOUSE_INT	0x33

/*	mouse_reset - returns -1 if no mouse, otherwise, no. of buttons	*/

int mouse_reset( void )

{
	union REGS reg;
	
	reg.x.ax = 0;
	int86( MOUSE_INT, & reg, & reg );
	
	if ( reg.x.ax == 0 ) {		/* if no mouse */
		return( -1 );
	}
	else {
		return( reg.x.bx );	/* return button count */
	}
}

/*	mouse_show_cursor - turns on the mouse cursor	*/

void mouse_show_cursor( void )

{
	union REGS reg;
	
	reg.x.ax = 1;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_hide_cursor - turns off the mouse cursor */

void mouse_hide_cursor( void )

{
	union REGS reg;
	
	reg.x.ax = 2;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_get_status - get position and button status	*/

void mouse_get_status(	short *buttons,
					short *x_pos,
					short *y_pos )

{
	union REGS reg;
	
	reg.x.ax = 3;

	int86( MOUSE_INT, & reg, & reg );

	*buttons = reg.x.bx;
	*x_pos = reg.x.cx;
	*y_pos = reg.x.dx;
}

/*	mouse_set_cursor - set cursor position	*/

void mouse_set_cursor( short x_pos, short y_pos )

{
	union REGS reg;
	
	reg.x.ax = 4;
	reg.x.cx = x_pos;
	reg.x.dx = y_pos;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_get_press - get button press status	*/

void mouse_get_press(	short button,
				short *status,
				short *count,
				short *x_pos,
				short *y_pos )

{
	union REGS reg;
	
	reg.x.ax = 5;
	reg.x.bx = button;

	int86( MOUSE_INT, & reg, & reg );
	
	*status = reg.x.ax;
	*count = reg.x.bx;
	*x_pos = reg.x.cx;
	*y_pos = reg.x.dx;
}

/*	mouse_get_release - get button release status	*/

void mouse_get_release(	short button,
					short *status,
					short *count,
					short *x_pos,
					short *y_pos )

{
	union REGS reg;
	
	reg.x.ax = 6;
	reg.x.bx = button;

	int86( MOUSE_INT, & reg, & reg );
	
	*status = reg.x.ax;
	*count = reg.x.bx;
	*x_pos = reg.x.cx;
	*y_pos = reg.x.dx;
}

/*	mouse_set_x_limits - set cursor x direction travel limits	*/

void mouse_set_x_limits( short x_min, short x_max )

{
	union REGS reg;
	
	reg.x.ax = 7;
	reg.x.cx = x_min;
	reg.x.dx = x_max;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_set_y_limits - set cursor y direction travel limits	*/

void mouse_set_y_limits( short y_min, short y_max )

{
	union REGS reg;
	
	reg.x.ax = 8;
	reg.x.cx = y_min;
	reg.x.dx = y_max;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_set_cursor_image - set new cursor image	*/

void mouse_set_cursor_image(	short x_hot,
					short y_hot,
					short *image )

{
	union REGS reg;
	struct SREGS sreg;
	short far *image_ptr;
	
	reg.x.ax = 9;
	reg.x.bx = x_hot;
	reg.x.cx = y_hot;
	reg.x.dx = FP_OFF( image );
	
	image_ptr = (short far *) image;
	sreg.ds = sreg.es = FP_SEG( image_ptr );

	int86x( MOUSE_INT, & reg, & reg, & sreg );
}

/*	mouse_set_text_cursor - set text cursor parameters	*/

void mouse_set_text_cursor(	short type, short start, short stop )

{
	union REGS reg;
	
	reg.x.ax = 10;
	reg.x.bx = type;
	reg.x.cx = start;
	reg.x.dx = stop;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_read_counters - read raw movement counts since last request  */

void mouse_read_counters( short *x_count, short *y_count )

{
	union REGS reg;
	
	reg.x.ax = 11;

	int86( MOUSE_INT, & reg, & reg );

	*x_count = reg.x.cx;
	*y_count = reg.x.dx;
}

/*	mouse_set_speed - set number of number of mickeys per 8 pixels	*/

void mouse_set_speed( short x_ratio, short y_ratio )

{
	union REGS reg;
	
	reg.x.ax = 15;
	reg.x.cx = x_ratio;
	reg.x.dx = y_ratio;

	int86( MOUSE_INT, & reg, & reg );
}

/*	mouse_set_double - set mouse speed at which cursor travel doubles  */

void mouse_set_double( short speed )

{
	union REGS reg;
	
	reg.x.ax = 19;
	reg.x.dx = speed;

	int86( MOUSE_INT, & reg, & reg );
}

--------------------------------------------CUT------------------------------------

/*	sample.c - sample program for Xez graphics routines,
			converted to Borland Turbo C 2.0 for MS-DOS

	This file shows a sample of the use of the Xez graphics routines.
*/

#include <stdio.h>
#include <stdlib.h>

#include <graphics.h>

#include "mouse.h"

/*----------------------------------------------------------------------*/

/*	procedure to get a mouse "click" - wait until any button is
		down, then wait until all released.  Return mouse
		position when all buttons released, and mask of all
		buttons pushed.
*/

void get_mouse_click( short *button_mask, short *x, short *y )

{
  short cur_buttons;			/* buttons currently pressed */

  do {
    mouse_get_status( & cur_buttons, x, y );
  } while ( cur_buttons == 0 );		/* wait until a button is pressed */
  
  *button_mask = cur_buttons;		/* initial mask */
  
  do {
    mouse_get_status( & cur_buttons, x, y );
    *button_mask |= cur_buttons;	/* add buttons to mask */
  } while ( cur_buttons != 0 );		/* wait until all buttons released */
}

/*----------------------------------------------------------------------*/

/*	main program	*/

void main( argc, argv )

int argc;
char *argv[];

{
  int status;
  short window_width;			/* window size (screen may be smaller)*/
  short window_height;
  short maxcolor;			/* maximum color (usually white) */
  short cur;
  short x, y;
  short dist;
  short button_mask;
  short button_count;
  int gdriver = DETECT;			/* graphics mode (auto detect) */
  int gmode = 0;

  /* Initialize graphics.  The environment variable BGI is expected
  	to contain the full path of the directory containing the Borland
  	Graphics Interface drivers (.BGI files)
  */

  initgraph( & gdriver, & gmode, getenv( "BGI" ) );
  if ( (status = graphresult()) != grOk ) {
    fprintf( stderr, "Graphics init error: %s\n", grapherrormsg( status ) );
    exit( 1 );
  }

  /* Get size and max color; use square area */

  window_width = getmaxx() + 1;
  window_height = getmaxy() + 1;
  if ( window_width > window_height ) {
    window_width = window_height;
  }
  else {
    window_height = window_width;
  }

  maxcolor = getmaxcolor();

  /* Initialize mouse.  A Microsoft compatible mouse driver must already
	be loaded.  Note that the mouse cursor must be off while
	drawing; this is the initial condition.
  */
	
  button_count = mouse_reset();

  if ( button_count <= 0 ) {
    closegraph();
    fprintf( stderr, "No mouse driver found\n" );
    exit( 1 );
  }

  /* Draw a large "X" in the window */

  for ( cur = 0; cur < window_width && cur < window_height; ++cur ) {
    putpixel( cur, cur, maxcolor );
    putpixel( cur, window_height-cur-1, maxcolor );
  }

  /* Draw a spiral */

  x = window_width / 2;			/* center */
  y = window_height / 2;
  dist = 0;				/* distance to move */

  while ( x >= 0  &&  x < window_width  &&  y >= 0  &&  y < window_height ) {

    for ( cur = 1, dist += 8; cur <= dist; ++cur ) {
      putpixel( x+cur, y, maxcolor );
    }
    x = x+dist;

    for ( cur = 1, dist += 8; cur <= dist; ++cur ) {
      putpixel( x, y+cur, maxcolor );
    }
    y = y+dist;

    for ( cur = 1, dist += 8; cur <= dist; ++cur ) {
      putpixel( x-cur, y, maxcolor );
    }
    x = x-dist;

    for ( cur = 1, dist += 8; cur <= dist; ++cur ) {
      putpixel( x, y-cur, maxcolor );
    }
    y = y-dist;
  }

  /* Wait for button press from mouse */

  mouse_show_cursor();				/* turn on mouse cursor */
  get_mouse_click( & button_mask, & x, & y );	/* wait for mouse click */

  closegraph();					/* exit graphics mode */

  printf( "Button mask %d at location (%d,%d)\n", button_mask, x, y );

  exit( 0 );
}