[comp.unix.xenix] mouse added to Vi

honzo@4gl.UUCP (04/11/87)

Some day's ago I asked the Net how the PC Mouse works. It happens to be
quite simple...

From: mcvax!masscomp!alang:
============================================================================
Serial mice normally run at 1200 baud.

When the mouse is moved, or buttons are pressed or released, 5 bytes of
information are sent.

The first byte tells the current button state. The high order 5 bits are the
pattern 10000 with the remaining 3 bits being the sate of the left, middle,
and right mouse buttons.

Bytes 2 and 3 are 8 bit signed values of delta x and delta y.

Bytes 4 and 5 are also 8 bit signed values of delta x and delta y, relative
to the previous two bytes. (ie. use both sets -- not just the first)

I'm not sure, but since you know that the data is being sent at a constant
rate, you might be able to infer the speed at which the mouse was being
moved from the difference between the two sets of x and y.

This information is for the mouse systems mouse, but this appears to have
become a standard amongst serial mice.

Alan Groupe
============================================================================

Thanks Alan! (and of course all the others not mentioned who send mail)

... which means that you can connect this (very cheap) mouse to any spare
serial line! To try the above out, I decided to add a mouse to vi. It does
not work perfect, but shows how you can use the mouse.

This will compile on any Sys V machine. And run on an ANSI type terminal,
provided that you map your keypad to the h j k l keys.

Button 1 send's ESC. Button 2 sends . (again). Button 3 will start the
context senzitive Pull Down Help function, but is not yet finished :-).
(Could be done though, thinking about it, you only need to send a ^L to
restore the Vi screen after you are done)

When your are going to use mvi regularly, I suggest that you remove your
bell from your terminal! (You'll find out why)

Any comments etc are welcome at mcvax!4gl!honzo

------code follows -----

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/[k]sh to create the files:
#	Makefile
#	mouse.c
#	mvi
# This archive created: Sat Apr 11 02:03:41 1987
# By:	honzo 
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat > 'Makefile' << \S!H!A!R
#
all:		mouse.do /dev/mouse mvi

mouse.do:	mouse.c
		cc mouse.c -o mouse.do

/dev/mouse:
		/etc/mknod /dev/mouse p

mvi:	
		chmod +x mvi
S!H!A!R
fi # end of overwriting check
if test -f 'mouse.c'
then
	echo shar: will not over-write existing file "'mouse.c'"
else
cat > 'mouse.c' << \S!H!A!R
/*
	mvi - Mouse vi, an example of using the PC Mouse
	This code will self-destroy when not used to make profit.
	Author: Honzo Svasek
*/

#include <stdio.h>
#include <termio.h>
#include <fcntl.h>

int	delta_x;	/* movement in x direction (horizontal) */
int	delta_y;	/* movement in y direction (vertical) */
char	but_1;		/* button 1, 0 = up, 1 = down */
char	but_2;		/* button 2, 0 = up, 1 = down */
char	but_3;		/* button 3, 0 = up, 1 = down */
int	fd;		/* fd of mouse */
FILE	*mouse, *o_mouse();

#define MOUSE_PORT	"com1.d"

main(argc, argv)
int	argc;
char	*argv[];
{
	char	command[80];
	int xnew=0, ynew=0, xold, yold;
	int i, c;

	if ((mouse = o_mouse(MOUSE_PORT)) == NULL) {
		perror(MOUSE_PORT);
		exit(-1);
	}

	for(;;) {
		r_mouse(mouse);
		if (but_1) {
			fputc('\033', stdout);
		}
		if (but_2) {
			fputc('.', stdout);
			fflush(stdout);
			fflush(mouse);
		}

		if (delta_y >  3) fputs("\033[B", stdout);
		if (delta_y < -3) fputs("\033[A", stdout);
		if (delta_x >  3) fputs("\033[C", stdout);
		if (delta_x < -3) fputs("\033[D", stdout);
		fflush(stdout);
	}
}

/* r_mouse - read a string of mouse data */

r_mouse(mouse)
FILE	*mouse;
{
	char	bn, x1, y1, x2, y2;

	while (!(bn = fgetc(mouse) & 0x80);
	x1 = fgetc(mouse);
	y1 = fgetc(mouse);
	x2 = fgetc(mouse);
	y2 = fgetc(mouse);

	delta_x = x1 > 128 ? x2 - x1 : x1 - x2;
	delta_y = y1 < 128 ? y2 - y1 : y1 - y2;
	but_1 = bn & 4 ? 0 : 1;
	but_2 = bn & 2 ? 0 : 1;
	but_3 = bn & 1 ? 0 : 1;

	return 0;
}

FILE *o_mouse(port)
char *port;
{
	char	device[25];
	struct termio tty;
	FILE	*fdopen();

	strcpy(device, "/dev/");
	strcat(device, port);

	/* mouse-tty parameters */
	tty.c_iflag = 0;
	tty.c_cflag = B1200 | CS8 | CREAD;
	tty.c_oflag = 0;
	tty.c_lflag = 0;
	tty.c_cc[4] = 5;
	tty.c_cc[5] = 5;

	if ((fd = open(device, O_RDONLY)) < 0) {
		perror(device);
		exit(-1);
	}
	ioctl(fd, TCSETA, &tty);
	return fdopen(fd, "r");
}
S!H!A!R
fi # end of overwriting check
if test -f 'mvi'
then
	echo shar: will not over-write existing file "'mvi'"
else
cat > 'mvi' << \S!H!A!R
# mvi - vi with mouse - you must be drunk!

if [ -p /dev/mouse -a -w /dev/mouse -a -r /dev/mouse ]
then
	vi $*  < /dev/mouse &
	mouse.do > /dev/mouse &
	cat -u > /dev/mouse
	kill -9 $! 
else
	echo "mvi: you must have a named pipe /dev/mouse"
fi
S!H!A!R
chmod +x 'mvi'
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
I_I(           _                        	UUCP: ..mcvax!honzo@4gl
I I ) Honzo Svasek @ 4GL Consultants b.v.	FIDO:  Honzo Svasek @ 500/333