import gpm from unix.schottelius.org

Signed-off-by: Nico Schottelius <nico@ikn.schottelius.org>
This commit is contained in:
Nico Schottelius 2009-10-08 22:52:35 +02:00
commit 95a46c5577
5930 changed files with 755263 additions and 0 deletions

View file

@ -0,0 +1,58 @@
/*
* disable-paste.c - trivial program to stop gpm from pasting the
* current selection until the next user action
*
* Copyright (C) 1998 Ian Zimmerman <itz@rahul.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include "headers/gpm.h"
#include "headers/gpmInt.h"
int
main(int argc, char** argv)
{
Gpm_Connect conn;
const int len = sizeof(Gpm_Connect);
int exit_status = 0;
conn.eventMask = (unsigned short)(-1); conn.defaultMask = 0;
conn.minMod = 0; conn.maxMod = (unsigned short)(-1);
if (0 > Gpm_Open(&conn,0)) {
fprintf(stderr,"disable-paste: cannot open mouse connection\n");
exit(1);
}
conn.vc = GPM_REQ_NOPASTE;
conn.pid = 0;
if (len > write(gpm_fd, &conn, len)) {
fprintf(stderr,"disable-paste: cannot write request\n");
exit_status = 2;
}
Gpm_Close();
exit(exit_status);
}

View file

@ -0,0 +1,110 @@
/*
* display-coords.c - a very simple gpm client
*
* Copyright 2007-2008 Nico Schottelius <nico-gpm2008 (at) schottelius.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Compile and link with: gcc -o display-buttons -lgpm display-buttons.c
*
********/
/*
* This client is connects to gpm and displays the following values until
* it is killed by control+c:
*
* left/middle/right button
* time: when packet was recievesd
* dtime: delta to the last packet
*
*/
#include <unistd.h> /* write, read, open */
#include <stdlib.h> /* strtol() */
#include <stdio.h> /* printf() */
#include <time.h> /* time() */
#include <errno.h> /* errno */
#include <gpm.h> /* gpm information */
/* display resulting data */
int display_data(Gpm_Event *event, void *data)
{
static time_t last = 0;
time_t now = time(NULL);
int delta;
delta = now - last;
last = now;
/* display time, delta time */
printf("[%d] delta: %ds",now,delta);
/* display mouse information */
printf(": p=%d, l=%1d, m=%1d, r=%1d, clicks=%d\n",
event->type & GPM_DOWN,
event->buttons & GPM_B_LEFT,
event->buttons & GPM_B_MIDDLE,
event->buttons & GPM_B_RIGHT,
event->clicks);
return 0;
}
int main(int argc, char **argv)
{
int vc; /* argv: console number */
Gpm_Connect conn; /* connection to gpm */
fd_set fds;
/* select virtual console, 0 if not set */
vc = (argc == 2) ? strtol(argv[1],NULL,10) : 0;
conn.eventMask = GPM_DRAG | GPM_DOWN | GPM_UP;
conn.defaultMask = ~GPM_HARD; /* inverted GPM_HARD mask */
conn.minMod = 0;
conn.maxMod = ~0;
if(Gpm_Open(&conn,vc) == -1) {
printf("Cannot connect to gpm!\n");
return 1;
}
if(gpm_fd == -2) {
printf("I must be run on the console\n");
return 1;
}
printf("\tp=pressed (0=release)\n\tl=left\n\tm=middle\n\tr=right\n");
while(1) { /* read data */
FD_ZERO(&fds);
FD_SET(gpm_fd, &fds);
if (select(gpm_fd+1, &fds, 0, 0, 0) < 0 && errno == EINTR)
continue;
if (FD_ISSET(gpm_fd, &fds)) {
Gpm_Event evt;
if (Gpm_GetEvent(&evt) > 0) {
display_data(&evt, NULL);
} else {
printf("Gpm_GetEvent failed\n");
}
}
}
Gpm_Close(); /* close connection */
return 0;
}

View file

@ -0,0 +1,104 @@
/*
* display-coords.c - a very simple gpm client
*
* Copyright 2007-2008 Nico Schottelius <nico-gpm2008 (at) schottelius.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Compile and link with: gcc -o display-coords -lgpm display-coords.c
*
********/
/*
* This client is connects to gpm and displays the following values until
* it is killed by control+c:
*
* x/y coords on the screen
* dx, dy: deltas
* time: when packet was recievesd
* dtime: delta to the last packet
*
*/
#include <unistd.h> /* write, read, open */
#include <stdlib.h> /* strtol() */
#include <stdio.h> /* printf() */
#include <time.h> /* time() */
#include <errno.h> /* errno */
#include <gpm.h> /* gpm information */
/* display resulting data */
int display_data(Gpm_Event *event, void *data)
{
static time_t last = 0;
time_t now = time(NULL);
int delta;
delta = now - last;
last = now;
/* display time, delta time */
printf("[%d] delta: %ds",now,delta);
/* display mouse information */
printf(": x=%2i, y=%2i, dx=%2i, dy=%2i\n", event->x, event->y, event->dx, event->dy);
return 0;
}
int main(int argc, char **argv)
{
int vc; /* argv: console number */
Gpm_Connect conn; /* connection to gpm */
fd_set fds;
/* select virtual console, 0 if not set */
vc = (argc == 2) ? strtol(argv[1],NULL,10) : 0;
conn.eventMask = GPM_MOVE; /* read only moves */
conn.defaultMask = ~GPM_HARD; /* inverted GPM_HARD mask */
conn.minMod = 0;
conn.maxMod = ~0;
if(Gpm_Open(&conn,vc) == -1) {
printf("Cannot connect to gpm!\n");
return 1;
}
if(gpm_fd == -2) {
printf("I must be run on the console\n");
return 1;
}
while(1) { /* read data */
FD_ZERO(&fds);
FD_SET(gpm_fd, &fds);
if (select(gpm_fd+1, &fds, 0, 0, 0) < 0 && errno == EINTR)
continue;
if (FD_ISSET(gpm_fd, &fds)) {
Gpm_Event evt;
if (Gpm_GetEvent(&evt) > 0) {
display_data(&evt, NULL);
} else {
printf("Gpm_GetEvent failed\n");
}
}
}
Gpm_Close(); /* close connection */
return 0;
}

View file

@ -0,0 +1,39 @@
/*
* Get gpm library and server version
*
* Copyright 2007-2008 Nico Schottelius <nico-gpm2008 (at) schottelius.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Compile and link with: gcc -lgpm
*
********/
#include <stdio.h> /* printf() */
#include <gpm.h> /* gpm information */
int main()
{
char *ver;
int intver;
ver = Gpm_GetLibVersion(&intver);
printf("lib: %s, %d\n",ver,intver);
ver = Gpm_GetServerVersion(&intver);
printf("srv: %s, %d\n",ver,intver);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,543 @@
/*
* hltest.c - a demo program for the high-level library.
*
* Copyright 1995 rubini@linux.it (Alessandro Rubini)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <termios.h>
#include "headers/gpm.h"
#ifndef min
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)>(b)?(a):(b))
#endif
/*
* If you happen to read this source to get insights about mouse
* management, note that most of this file is concerned with user
* interface and screen handling. The mouse-related part begines
* at "MOUSE-BEGIN" (so you can use your editor capabilities to
* look for strings).
*
* If you use parts of this program in your own one, I'd like some credit.
* If you want to overcome the gnu copyleft though using parts of this
* program, just tell me about it, and I'll change the copyright.
*/
/* this is used as clientdata */
typedef struct WinInfo {
char color;
int number;
short hei,wid;
Gpm_Roi *roi;
} WinInfo;
WinInfo left_cldata; /* for the msg bar */
int colors[]={0x40,0x60,0x20,0x30,0x47,0x67,0x27,0x37};
#define NR_COLORS 8
#define LEFTWID 22
/* Dirty: use escape sequences and /dev/vcs (don't want to learn curses) */
#define CLEAR (printf("\x1b[H\x1b[J"),fflush(stdout))
int dev_vcs=-1;
int wid,hei,vcsize;
/*
* These two functions are only involved in the user interface:
* dump and restore the screen to keep things up to date.
*/
unsigned short clear_sel_args[6]={0, 0,0, 0,0, 4};
unsigned char *clear_sel_arg= (unsigned char *)clear_sel_args+1;
static inline int scrdump(char *buf)
{
clear_sel_arg[0]=2; /* clear_selection */
ioctl(fileno(stdin),TIOCLINUX,clear_sel_arg);
lseek (dev_vcs, 0, SEEK_SET);
return read(dev_vcs,buf,vcsize);
}
static inline int scrrestore(char *buf)
{
clear_sel_arg[0]=2; /* clear_selection */
ioctl(fileno(stdin),TIOCLINUX,clear_sel_arg);
lseek (dev_vcs, 0, SEEK_SET);
return write(dev_vcs,buf,vcsize);
}
/* I don't like curses, so I'm doing low level stuff here */
static void raw(void)
{
struct termios it;
tcgetattr(fileno(stdin),&it);
it.c_lflag &= ~(ICANON);
it.c_lflag &= ~(ECHO);
it.c_iflag &= ~(INPCK|ISTRIP|IXON);
it.c_oflag &= ~(OPOST);
it.c_cc[VMIN] = 1;
it.c_cc[VTIME] = 0;
tcsetattr(fileno(stdin),TCSANOW,&it);
}
static void noraw(void)
{
struct termios it;
tcgetattr(fileno(stdin),&it);
it.c_lflag |= ICANON;
it.c_lflag |= ECHO;
it.c_iflag |= IXON;
it.c_oflag |= OPOST;
tcsetattr(fileno(stdin),TCSANOW,&it);
}
/* this one is the signal handler */
void killed(int signo)
{
CLEAR;
fprintf(stderr,"hltest: killed by signal %i\r\n",signo);
noraw();
exit(0);
}
char *dumpbuf;
char *dumpbuf_clean;
#define DUMPCHAR(x,y) (dumpbuf+4+2*((y)*wid+(x)))
#define DUMPATTR(x,y) (dumpbuf+5+2*((y)*wid+(x)))
/*
* This function draws one window on top of the others
*/
static inline int drawwin(Gpm_Roi *which)
{
char *curr;
char name[5];
#define GOTO(x,y) (curr=DUMPCHAR(x,y))
#define PUTC(c,a) (*(curr++)=(c),*(curr++)=a)
#define ULCORNER 0xc9
#define URCORNER 0xbb
#define LLCORNER 0xc8
#define LRCORNER 0xbc
#define HORLINE 0xcd
#define VERLINE 0xba
int attrib=((WinInfo *)which->clientdata)->color;
int i,j;
/* top border */
GOTO(which->xMin,which->yMin);
PUTC(ULCORNER,attrib);
for (i=which->xMin+1; i<which->xMax; i++)
PUTC(HORLINE,attrib);
PUTC(URCORNER,attrib);
/* sides and items */
for (j=which->yMin+1;j<which->yMax;j++)
{
GOTO(which->xMin,j);
PUTC(VERLINE,attrib);
for (i=which->xMin+1; i<which->xMax; i++)
PUTC(' ',attrib);
PUTC(VERLINE,attrib);
}
/* bottom border */
GOTO(which->xMin,which->yMax);
PUTC(LLCORNER,attrib);
for (i=which->xMin+1; i<which->xMax; i++)
PUTC(HORLINE,attrib);
PUTC(LRCORNER,attrib);
/* name */
sprintf(name,"%3i",((WinInfo *)which->clientdata)->number);
GOTO(which->xMin+1,which->yMin+1);
for (i=0;name[i];i++)
PUTC(name[i],attrib);
return 0;
}
/* and finally, draw them all (recursive) */
int drawthemall(Gpm_Roi *this)
{
if (this->next)
drawthemall(this->next);
else
memcpy(dumpbuf,dumpbuf_clean,vcsize);
return drawwin(this);
}
/*
* This one writes all the messages in the right position
*/
int newmsg(int window, char *msg)
{
static char *data=NULL;
static char **strings;
static int current, last;
static time_t t;
int i,j;
/* first time, alloc material */
if (!data)
{
data=malloc((LEFTWID-2)*(hei-2));
strings=malloc(hei*sizeof(char *));
if(!data || !strings) { perror("malloc()"); exit(1); }
memset(data,' ',(LEFTWID-2)*(hei-2));
for (i=0;i<hei-2;i++)
strings[i]=data+(LEFTWID-2)*i, strings[i][19]='\0';
current=0;
}
if (msg) /* if sth new */
{
time(&t);
strftime(strings[current],15,"%M:%S ",localtime(&t));
sprintf(strings[current]+strlen(strings[current]),"%i: ",window);
strncat(strings[current],msg,LEFTWID-2-strlen(strings[current]));
for (i=strlen(strings[current]);i<19;i++)
strings[current][i]=' ';
strings[current][i]=0;
last=current; current++; current%=(hei-2);
}
else /* draw them all */
for (i=1,j=current; j%=(hei-2), i<hei-2; i++,j++)
printf("\x1B[%03i;%03iH%s",j+2,2,strings[j]); /* y and x */
/* write only the current one */
printf("\x1B[%03i;%03iH%s\x1B[%03i;%03iH%s",
last+2,2,strings[last],current+2,2," ");
fflush(stdout);
return 0;
}
/*
* Wrapper: refresh the whole screen
*/
static inline void dorefresh(void)
{
static unsigned short clear_sel_args[6]={0, 0,0, 0,0, 4};
static unsigned char *clear_sel_arg= (unsigned char *)clear_sel_args+1;
drawthemall(gpm_roi);
clear_sel_arg[0]=2; /* clear_selection */
ioctl(fileno(stdin),TIOCLINUX,clear_sel_arg);
scrrestore(dumpbuf);
newmsg(0,NULL);
}
/*============================================================ MOUSE-BEGIN */
/*
* In this sample program, I use only one handler, which reports on the
* screen any event it gets. The clientdata received is the one I pass to
* Gpm_PushRoi on creation, and is used to differentiate them
*/
int handler(Gpm_Event *ePtr, void *clientdata)
{
WinInfo *info=clientdata;
int number=info->number;
int delta;
if (ePtr->type&GPM_ENTER)
{ newmsg(number,"enter"); return 0; }
if (ePtr->type&GPM_LEAVE)
{ newmsg(number,"leave"); return 0; }
if (ePtr->type&GPM_MOVE)
{ newmsg(number,"move"); return 0; }
if (ePtr->type&GPM_DOWN)
{newmsg(number,"press"); return 0; }
if (ePtr->type&GPM_DRAG)
{
newmsg(number,"drag");
if (!(ePtr->buttons&GPM_B_LEFT)) return 0;
/*
* Implement window motion
*/
delta=0;
if (ePtr->dx < 0) delta=max(ePtr->dx,LEFTWID-info->roi->xMin);
else if (ePtr->dx > 0) delta=min(ePtr->dx,wid-1 - info->roi->xMax);
if (delta) { info->roi->xMin+=delta; info->roi->xMax+=delta; }
delta=0;
if (ePtr->dy < 0) delta=max(ePtr->dy,0 - info->roi->yMin);
else if (ePtr->dy > 0) delta=min(ePtr->dy,hei-1 - info->roi->yMax);
if (delta) { info->roi->yMin+=delta; info->roi->yMax+=delta; }
Gpm_RaiseRoi(info->roi,NULL);
dorefresh(); return 0;
}
newmsg(number,"release");
/*
* "up" events can be double or triple,
* moreover, they can happen out of the region
*/
if (!(ePtr->type&GPM_SINGLE)) return 0;
if (ePtr->x<0 || ePtr->y<0) return 0;
if (ePtr->x>info->wid-1 || ePtr->y>info->hei-1) return 0;
/*
* Ok, it is has been a double click, and it is within our area
*/
switch(ePtr->buttons)
{
case GPM_B_LEFT: Gpm_RaiseRoi(info->roi,NULL); break;
case GPM_B_MIDDLE: Gpm_LowerRoi(info->roi,NULL); break;
case GPM_B_RIGHT:
Gpm_PopRoi(info->roi); free(info); break;
}
dorefresh();
return 0;
}
/*
* the following function creates a window, with the four corners as
* specified by the arguments.
*/
int wincreate(int x, int y, int X, int Y)
{
static int winno=0;
Gpm_Roi*roi;
WinInfo *cldata;
int tmp;
if (X<x) tmp=X,X=x,x=tmp;
if (Y<y) tmp=Y,Y=y,y=tmp;
if (X-x<5) X=x+4;
if (Y-y<3) Y=y+2;
if (X>=wid) X=wid-1;
if (Y>=hei) Y=hei-1;
if (x<LEFTWID) x=LEFTWID;
if (y<0) y=0;
cldata=malloc(sizeof(WinInfo));
roi=Gpm_PushRoi(x,y,X,Y,
GPM_DOWN|GPM_UP|GPM_DRAG|GPM_ENTER|GPM_LEAVE,
handler,cldata);
if (!cldata || !roi) { perror("malloc()"); exit(1); }
/* don't get modifiers */
roi->maxMod=0;
/* put a backpointer */
cldata->roi=roi;
/* init the window */
winno++;
cldata->number=winno;
cldata->color=colors[winno%NR_COLORS];
cldata->wid=X-x+1;
cldata->hei=Y-y+1;
dorefresh();
return 0;
}
/*
* This extra handler is only used for the background and left bar
*/
int xhandler(Gpm_Event *ePtr, void *clientdata)
{
static int x=0,y=0;
int back=0;
char msg[32];
msg[0]='\0';
if (ePtr->type==GPM_MOVE) return 0;
if (!clientdata)
strcpy(msg,"bg"),back++;
if (ePtr->type&GPM_DOWN)
{
strcat(msg," down");
if (back) x=ePtr->x,y=ePtr->y;
}
if (ePtr->type&GPM_UP)
{
strcat(msg," up");
if (back) wincreate(x,y,ePtr->x,ePtr->y);
}
newmsg(0,msg);
/* GPM_DRAWPOINTER(ePtr); useless, gpm_visiblepointer is set to 1 BUG */
return 0;
}
/*============================================================ MOUSE-END */
/*
* This function is not interesting, it is only involved in setting up
* things. The real work has already been done.
*/
int main(int argc, char **argv)
{
Gpm_Connect conn;
char *s, t[4];
char devname[32]; /* very secure buffer ... */
int c;
int vc;
struct winsize win;
if (argc>1) {
fprintf(stderr,"%s: This program is meant to be interactive, "
"no option is needed\n",argv[0]);
exit(1);
}
if (!(s=ttyname(fileno(stdin)))) {
perror("stdin");
exit(1);
}
/* retrieve everything */
conn.eventMask=~0;
conn.defaultMask=GPM_MOVE|GPM_HARD;
conn.maxMod=~0;
conn.minMod=0;
if (sscanf(s,"/dev/tty%d%s",&vc,t)!=1) {
if (sscanf(s,"/dev/vc/%d%s",&vc,t)!=1) {
fprintf(stderr,"stdin: not a system console\n");
exit(1);
}
}
/* open your dump/restore buffers */
sprintf(devname,"/dev/vcs%i",vc);
if ((dev_vcs=open(devname,O_RDWR))<0) {
perror(devname);
sprintf(devname,"/dev/vcc/%i",vc);
if ((dev_vcs=open(devname,O_RDWR))<0) {
perror(devname);
exit(1);
}
}
if (Gpm_Open(&conn,0) == -1) {
fprintf(stderr,"%s: Can't open mouse connection\n",argv[0]);
exit(1);
}
Gpm_Close(); /* don't be clubbered by events now */
signal(SIGWINCH,killed); /* don't handle winchange */
signal(SIGINT,killed); /* control-C kills us */
CLEAR;
printf("\t\t\t This program is a demonstration of the use of the\n"
"\t\t\t high level gpm library. It is a tiny application\n"
"\t\t\t not really useful, but you may be interested in\n"
"\t\t\t reading the source (as well as the docs).\n\n"
"\t\t\tWorkings:\n"
"\t\t\t You can create windows by clicking on the background\n"
"\t\t\t and dragging out the desired size (minimun is 5x3).\n"
"\t\t\t The first 20 columns are reserved for messages.\n"
"\t\t\t there is always one invisible window on the backgruond\n"
"\t\t\t which gets shift-mouse events. All the others are only\n"
"\t\t\t sensitive to mouse-only events (the library leaves you\n"
"\t\t\t free about that, but this program makes things simple\n"
"\n"
"\t\t\t The left button raises the window\n"
"\t\t\t The middle (if any) lowers the window\n"
"\t\t\t The right one destroys the window\n\n"
"\t\t\t Keyboard focus is changed by mouse motion\n"
"\t\t\t Control-C kills the program\n\n"
"\t\t\tEnjoy\n\t\t\t The Author\n\n"
);
/* Ok, now retrieve window info, go to raw mode, and start it all */
ioctl(fileno(stdin), TIOCGWINSZ, &win);
wid=win.ws_col; hei=win.ws_row;
vcsize=hei*wid*2+4;
dumpbuf=malloc(vcsize); dumpbuf_clean=malloc(vcsize);
if (!dumpbuf || ! dumpbuf_clean)
{ perror("malloc()"); exit(1); }
scrdump(dumpbuf_clean);
gpm_zerobased=1; gpm_visiblepointer=1;
if (Gpm_Open(&conn,0)==-1)
{ fprintf(stderr,"%s: Can't open mouse connection\n",argv[0]); exit(1); }
/* Prepare the leftish roi, and the catch-all on the background */
left_cldata.color=0x07; left_cldata.number=0;
left_cldata.hei=hei; left_cldata.wid=LEFTWID;
Gpm_PushRoi(0,0,LEFTWID-1,hei-1,
GPM_DOWN|GPM_DRAG|GPM_UP|GPM_ENTER|GPM_LEAVE,
xhandler,&left_cldata);
gpm_roi_handler=xhandler;
gpm_roi_data=NULL;
raw();
newmsg(0,NULL); /* init data structures */
while((c=Gpm_Getchar())!=EOF) {
char s[32];
Gpm_Roi *roi;
roi=gpm_current_roi;
sprintf(s,"0x%x",c);
if (c>0x1f && c<0x7f)
sprintf(s+strlen(s)," ('%c')",c);
newmsg(roi ? ((WinInfo *)roi->clientdata)->number : 0,s);
}
noraw();
exit(0);
}

View file

@ -0,0 +1,488 @@
/*
* mev.c - simple client to print mouse events (gpm-Linux)
*
* Copyright 1994,1995 rubini@linux.it (Alessandro Rubini)
* Copyright (C) 1998 Ian Zimmerman <itz@rahul.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********/
/*
* This client is meant to be used both interactively to check
* that gpm is working, and as a background process to convert gpm events
* to textual strings. I'm using it to handle Linux mouse
* events to emacs
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <linux/keyboard.h> /* to use KG_SHIFT and so on */
#define ALL_KEY_MODS ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_ALTGR)|(1<<KG_CTRL))
#include "headers/message.h" /* messages */
#include "headers/gpm.h"
#define GPM_NAME "gpm"
#define GPM_DATE "X-Mas 2002"
char *prgname;
struct node {char *name; int flag;};
struct node tableEv[]= {
{"move", GPM_MOVE},
{"drag", GPM_DRAG},
{"down", GPM_DOWN},
{"up", GPM_UP},
{"press", GPM_DOWN},
{"release", GPM_UP},
{"motion", GPM_MOVE | GPM_DRAG},
{"hard", GPM_HARD},
{"any", ~0},
{"all", ~0},
{"none", 0},
{NULL,0}
};
struct node tableMod[]= {
{"shift", 1<<KG_SHIFT},
{"anyAlt", 1<<KG_ALT | 1<<KG_ALTGR},
{"leftAlt", 1<<KG_ALT},
{"rightAlt", 1<<KG_ALTGR},
{"control", 1<<KG_CTRL},
{"any", ~0},
{"all", ~0},
{"none", 0},
{NULL,0}
};
/* provide defaults */
int opt_mask = ~0; /* get everything */
int opt_default = ~GPM_HARD; /* pass everithing unused */
int opt_minMod = 0; /* run always */
int opt_maxMod = ~0; /* with any modifier */
int opt_intrct = 0;
int opt_vc = 0; /* by default get the current vc */
int opt_emacs = 0;
int opt_fit = 0;
int opt_pointer = 0;
/*===================================================================*/
int user_handler(Gpm_Event *event, void *data)
{
if (opt_fit) Gpm_FitEvent(event);
printf("mouse: event 0x%02X, at %2i,%2i (delta %2i,%2i), "
"buttons %i, modifiers 0x%02X\r\n",
event->type,
event->x, event->y,
event->dx, event->dy,
event->buttons, event->modifiers);
if (event->type & (GPM_DRAG|GPM_DOWN)) {
if (0 != opt_pointer) {
GPM_DRAWPOINTER(event);
} /*if*/
} /*if*/
return 0;
}
/*-------------------------------------------------------------------*/
int emacs_handler(Gpm_Event *event, void *data)
{
int i,j;
static int dragX, dragY;
static char buffer[64];
/* itz Mon Mar 23 20:54:54 PST 1998 emacs likes the modifier bits in
alphabetical order, so I'll use a lookup table instead of a loop; it
is faster anyways */
/* static char *s_mod[]={"S-","M-","C-","M-",NULL}; */
static char *s_mod[] = {
"", /* 000 */
"S-", /* 001 */
"M-", /* 002 */
"M-S-", /* 003 */
"C-", /* 004 */
"C-S-", /* 005 */
"C-M-", /* 006 */
"C-M-S-", /* 007 */
/* idea: maybe we should map AltGr to Emacs Alt instead of Meta? */
"M-", /* 010 */
"M-S-", /* 011 */
"M-", /* 012 */
"M-S-", /* 013 */
"C-M-", /* 014 */
"C-M-S-", /* 015 */
"C-M-", /* 016 */
"C-M-S-", /* 017 */
};
/* itz Mon Mar 23 08:23:14 PST 1998 what emacs calls a `drag' event
is our `up' event with coordinates different from the `down'
event. What gpm calls `drag' is just `mouse-movement' to emacs. */
static char *s_type[]={"mouse-movement", "mouse-movement","down-mouse-","mouse-",NULL};
static char *s_button[]={"3","2","1",NULL};
static char *s_multi[]={"double-", "triple-", 0};
static char s_count[]="23";
char count = '1';
struct timeval tv_cur;
long timestamp;
static long dragTime;
/* itz Mon Mar 23 08:27:53 PST 1998 this flag is needed because even
if the final coordinates of a drag are identical to the initial
ones, it is still a drag if there was any movement in between. Sigh. */
static int dragFlag = 0;
gettimeofday(&tv_cur, 0);
timestamp = ((short)tv_cur.tv_sec) * 1000 + (tv_cur.tv_usec / 1000);
if (opt_fit) Gpm_FitEvent(event);
buffer[0]=0;
/* itz Sun Mar 22 19:09:04 PST 1998 Emacs doesn't understand
modifiers on motion events. */
if (!(event->type & (GPM_MOVE|GPM_DRAG))) {
/* modifiers */
strcpy(buffer, s_mod[event->modifiers & ALL_KEY_MODS]);
/* multiple */
for (i=0, j=GPM_DOUBLE; s_multi[i]; i++, j<<=1)
if (event->type & j) {
count = s_count[i];
strcat(buffer,s_multi[i]);
} /*if*/
} /*if*/
if (event->type & GPM_DRAG) {
dragFlag = 1;
} /*if*/
/* itz Mon Mar 23 08:26:33 PST 1998 up-event after movement is a drag. */
if ((event->type & GPM_UP) && dragFlag) {
strcat(buffer, "drag-");
} /*if*/
/* type */
for (i=0, j=GPM_MOVE; s_type[i]; i++, j<<=1)
if (event->type & j)
strcat(buffer,s_type[i]);
/* itz Sun Mar 22 19:09:04 PST 1998 Emacs doesn't understand
modifiers on motion events. */
if (!(event->type & (GPM_MOVE|GPM_DRAG)))
/* button */
for (i=0, j=GPM_B_RIGHT; s_button[i]; i++, j<<=1)
if (event->buttons & j)
strcat(buffer,s_button[i]);
if ((event->type & GPM_UP) && dragFlag) {
printf("(%s ((%i . %i) %ld) %c ((%i . %i) %ld))\n",
buffer,
event->x, event->y, timestamp,
count,
dragX, dragY, dragTime);
} else if (event->type & (GPM_DOWN|GPM_UP)) {
printf("(%s ((%i . %i) %ld) %c)\n",
buffer, event->x, event->y, timestamp, count);
} else if (event->type & (GPM_MOVE|GPM_DRAG)) {
printf("(%s ((%i . %i) %ld))\n",
buffer, event->x, event->y, timestamp);
} /*if*/
if (event->type & GPM_DOWN) {
dragX=event->x;
dragY=event->y;
dragTime=timestamp;
dragFlag = 0;
} /*if*/
if (event->type & (GPM_DRAG|GPM_DOWN)) {
if (0 == opt_pointer) {
GPM_DRAWPOINTER(event);
} /*if*/
} /*if*/
return 0;
}
/*===================================================================*/
int usage(void)
{
//printf( "(" GPM_NAME ") " GPM_RELEASE ", " GPM_DATE "\n"
printf( "(" GPM_NAME ") , " GPM_DATE "\n"
"Usage: %s [options]\n",prgname);
printf(" Valid options are\n"
" -C <number> choose virtual console (beware of it)\n"
" -d <number> choose the default mask\n"
" -e <number> choose the eventMask\n"
" -E emacs-mode\n"
" -i accept commands from stdin\n"
" -f fit drag events inside the screen\n"
" -m <number> minimum modifier mask\n"
" -M <number> maximum modifier mask\n"
" -p show pointer while dragging\n"
" -u user-mode (default)\n"
);
return 1;
}
/*===================================================================*/
#define PARSE_EVENTS 0
#define PARSE_MODIFIERS 1
void getmask(char *arg, int which, int* where)
{
int last=0, value=0;
char *cur;
struct node *table, *n;
int mode = 0; /* 0 = set, 1 = add, 2 = subtract */
if ('+' == arg[0]) {
mode = 1;
++arg;
} else if ('-' == arg[0]) {
mode = 2;
++arg;
}
if (isdigit(arg[0])) {
switch(mode) {
case 0: *where = atoi(arg); break;
case 1: *where |= atoi(arg); break;
case 2: *where &= ~atoi(arg); break;
} /*switch*/
return;
} /*if*/
table= (PARSE_MODIFIERS == which) ? tableMod : tableEv;
while (1)
{
while (*arg && !isalnum(*arg)) arg++; /* skip delimiters */
cur=arg;
while(isalnum(*cur)) cur++; /* scan the word */
if (!*cur) last++;
*cur=0;
for (n=table;n->name;n++)
if (!strcmp(n->name,arg))
{
value |= n->flag;
break;
}
if (!n->name) fprintf(stderr,"%s: Incorrect flag \"%s\"\n",prgname,arg);
if (last) break;
cur++; arg=cur;
}
switch(mode) {
case 0: *where = value; break;
case 1: *where |= value; break;
case 2: *where &= ~value; break;
} /*switch*/
}
/*===================================================================*/
int cmdline(int argc, char **argv, char *options)
{
int opt;
while ((opt = getopt(argc, argv, options)) != -1)
{
switch (opt)
{
/* itz Tue Mar 24 17:11:52 PST 1998 i hate options that do
too much. Made them orthogonal. */
case 'C': sscanf(optarg,"%x",&opt_vc); break;
case 'd': getmask(optarg, PARSE_EVENTS, &opt_default); break;
case 'e': getmask(optarg, PARSE_EVENTS, &opt_mask); break;
case 'E': opt_emacs = 1; break;
case 'i': opt_intrct=1; break;
case 'f': opt_fit=1; break;
case 'm': getmask(optarg, PARSE_MODIFIERS, &opt_minMod); break;
case 'M': getmask(optarg, PARSE_MODIFIERS, &opt_maxMod); break;
case 'p': opt_pointer =1; break;
case 'u': opt_emacs=0; break;
default: return 1;
}
}
return 0;
}
void
do_snapshot()
{
Gpm_Event event;
int i=Gpm_GetSnapshot(&event);
char *s;
if (-1 == i) {
fprintf(stderr,"Warning: cannot get snapshot!\n");
fprintf(stderr,"Have you run \"configure\" and \"make install\"?\n");
return;
} /*if*/
fprintf(stderr,"Mouse has %d buttons\n",i);
fprintf(stderr,"Currently sits at (%d,%d)\n",event.x,event.y);
fprintf(stderr,"The window is %d columns by %d rows\n",event.dx,event.dy);
s=Gpm_GetLibVersion(&i);
fprintf(stderr,"The library is version \"%s\" (%i)\n",s,i);
s=Gpm_GetServerVersion(&i);
fprintf(stderr,"The daemon is version \"%s\" (%i)\n",s,i);
fprintf(stderr,"The current console is %d, with modifiers 0x%02x\n",
event.vc,event.modifiers);
fprintf(stderr,"The button mask is 0x%02X\n",event.buttons);
}
/*===================================================================*/
int interact(char *cmd) /* returns 0 on success and !=0 on error */
{
Gpm_Connect conn;
int argc=0;
char *argv[20];
if (*cmd && cmd[strlen(cmd)-1]=='\n')
cmd[strlen(cmd)-1]='\0';
if (!*cmd) return 0;
/*
* Interaction is accomplished by building an argv and passing it to
* cmdline(), to use the same syntax used to invoke the program
*/
while (argc<19)
{
while(isspace(*cmd)) cmd++;
argv[argc++]=cmd;
while (*cmd && isgraph(*cmd)) cmd++;
if (!*cmd) break;
*cmd=0;
cmd++;
}
argv[argc]=NULL;
if (!strcmp(argv[0],"pop")) {
return (Gpm_Close()==0 ? 1 : 0); /* a different convention on ret values */
} /*if*/
if (!strcmp(argv[0],"info")) {
fprintf(stderr,"The stack of connection info is %i depth\n",gpm_flag);
return 0;
} /*if*/
if (!strcmp(argv[0],"quit")) {
exit(0);
} /*if*/
if (!strcmp(argv[0],"snapshot")) {
do_snapshot();
return 0;
} /*if*/
optind=0; /* scan the entire line */
if (strcmp(argv[0],"push") || cmdline(argc,argv,"d:e:m:M:")) {
fprintf(stderr,"Syntax error in input line\n");
return 0;
} /*if*/
conn.eventMask=opt_mask;
conn.defaultMask=opt_default;
conn.maxMod=opt_maxMod;
conn.minMod=opt_minMod;
if (Gpm_Open(&conn,opt_vc)==-1)
{
fprintf(stderr,"%s: Can't open mouse connection\r\n",argv[0]);
return 1;
}
return 0;
}
/*===================================================================*/
int main(int argc, char **argv)
{
Gpm_Connect conn;
char cmd[128];
Gpm_Handler* my_handler; /* not the real gpm handler! */
fd_set readset;
prgname=argv[0];
if (cmdline(argc,argv,"C:d:e:Efim:M:pu")) exit(usage());
gpm_zerobased = opt_emacs;
conn.eventMask=opt_mask;
conn.defaultMask=opt_default;
conn.maxMod=opt_maxMod;
conn.minMod=opt_minMod;
if (Gpm_Open(&conn,opt_vc) == -1) {
gpm_report(GPM_PR_ERR,"%s: Can't open mouse connection\n",prgname);
exit(1);
} else if (gpm_fd == -2) {
gpm_report(GPM_PR_OOPS,"%s: use rmev to see gpm events in xterm or rxvt\n",prgname);
}
gpm_report(GPM_PR_DEBUG,"STILL RUNNING_1");
my_handler= opt_emacs ? emacs_handler : user_handler;
/* itz Sun Mar 22 09:51:33 PST 1998 needed in case the output is a pipe */
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stdin, 0, _IOLBF, 0);
while(1) { /* forever */
FD_ZERO(&readset);
FD_SET(gpm_fd, &readset);
if (opt_intrct) {
FD_SET(STDIN_FILENO, &readset);
}
if (select(gpm_fd+1, &readset, 0, 0, 0) < 0 && errno == EINTR)
continue;
if (FD_ISSET(STDIN_FILENO, &readset)) {
if (0 == fgets(cmd, sizeof(cmd), stdin) || interact(cmd)) {
exit(0); /* ^D typed on input */
} /*if*/
} /*if*/
if (FD_ISSET(gpm_fd, &readset)) {
Gpm_Event evt;
if (Gpm_GetEvent(&evt) > 0) {
my_handler(&evt, 0);
} else {
fprintf(stderr, "mev says : Oops, Gpm_GetEvent()\n");
}
} /*if*/
} /*while*/
/*....................................... Done */
while (Gpm_Close()); /* close all the stack */
exit(0);
}

View file

@ -0,0 +1,740 @@
/*
* mouse-test.c
*
* Copyright 1995 rubini@linux.it (Alessandro Rubini)
* Copyright (C) 1998 Ian Zimmerman <itz@rahul.net>
* Copyright (C) 2002-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* Tue, 5 Jan 1999 23:15:23 +0000, modified by James Troup <james@nocrew.org>:
* (main): exclude devices with a minor number of 130 from
* the device probe to avoid causing spontaneous reboots on machines
* where watchdog is used. Reported by Jim Studt <jim@federated.com>
* [Debian bug report #22602]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********/
/* This code is horrible. Browse it at your risk */
/* hmm..read worse code before :) -nicos */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <termios.h>
#include "headers/message.h" /* to print */
#include "headers/gpmInt.h" /* to get mouse types */
#include "headers/daemon.h" /* FIXME: do not use that..rewrite mouse-test, anyway */
#ifndef min
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)>(b)?(a):(b))
#endif
/* this material is needed to pass options to mice.c */
struct mouse_features mymouse = {
DEF_TYPE, DEF_DEV, DEF_SEQUENCE,
DEF_BAUD, DEF_SAMPLE, DEF_DELTA, DEF_ACCEL, DEF_SCALE, DEF_SCALE /*scaley*/,
DEF_TIME, DEF_CLUSTER, DEF_THREE, DEF_GLIDEPOINT_TAP,
(char *)NULL /* extra */,
(Gpm_Type *)NULL,
-1 /* fd */
};
/* and this is a workaroud */
struct winsize win;
/* this too */
struct options option;
struct mouse_features *which_mouse=&mymouse;
char *progname;
char *consolename;
int devcount=0;
int typecount=0;
struct item {
Gpm_Type *this;
struct item *next;
};
struct device {
char *name;
int fd;
struct device *next;
};
static int message(void)
{
printf("This program is designed to help you in detecting what type your\n"
"mouse is. Please follow the instructions of this program. If you're\n"
"bored before it is done, you can always press your 'Interrupt' key\n"
"(usually Ctrl-C)\n\n");
printf("\t *** Remember: don't run any software which reads the mouse device\n"
"\t *** while making this test. This includes \"gpm\","
"\"selection\", \"X\"\n\n");
printf("Note that this program is by no means complete, and its main role is\n"
"to detect how does the middle button work on serial mice\n");
return 0;
}
/* I don't like curses, so I'm doing low level stuff here */
#define GOTOXY(f,x,y) fprintf(f,"\x1B[%03i;%03iH",y,x)
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
static void raw(void)
{
struct termios it;
tcgetattr(fileno(stdin),&it);
it.c_lflag &= ~(ICANON);
it.c_lflag &= ~(ECHO);
it.c_iflag &= ~(INPCK|ISTRIP|IXON);
it.c_oflag &= ~(OPOST);
it.c_cc[VMIN] = 1;
it.c_cc[VTIME] = 0;
tcsetattr(fileno(stdin),TCSANOW,&it);
}
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
static void noraw(void)
{
struct termios it;
tcgetattr(fileno(stdin),&it);
it.c_lflag |= ICANON;
it.c_lflag |= ECHO;
it.c_iflag |= IXON;
it.c_oflag |= OPOST;
tcsetattr(fileno(stdin),TCSANOW,&it);
}
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
void killed(int signo)
{
fprintf(stderr,"mouse-test: killed by signal %i\r\n",signo);
noraw();
exit(0);
}
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
struct device **gpm_makedev(struct device **current, char *name)
{
int fd; int modes;
if ((fd=open(name,O_RDWR|O_NONBLOCK))==-1) {
perror(name);
return current;
}
modes = fcntl(fd, F_GETFL);
if (0 > fcntl(fd, F_SETFL, modes & ~O_NONBLOCK)) {
close(fd);
perror(name);
return current;
}
*current=malloc(sizeof(struct device));
if (!*current) gpm_report(GPM_PR_OOPS,"malloc()");
(*current)->name=strdup(name);
if (!(*current)->name) gpm_report(GPM_PR_OOPS,"malloc()");
(*current)->fd=fd;
(*current)->next=NULL;
devcount++;
return &((*current)->next);
}
Gpm_Type *(*I_serial)(int fd, unsigned short flags, struct Gpm_Type *type,
int argc, char **argv);
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
int mousereopen(int oldfd, char *name, Gpm_Type *type)
{
int fd;
if (!type) type=mice+1; /* ms */
close(oldfd);
usleep(100000);
fd=open(name,O_RDWR);
if (fd < 0) gpm_report(GPM_PR_OOPS,name);
(*I_serial)(fd,type->flags,type,1,&type->name); /* ms initialization */
return fd;
}
int noneofthem(void)
{
noraw();
printf("\n\nSomething went wrong, I didn't manage to detect your"
"protocol\n\nFeel free to report your problems to the author\n");
exit(1);
}
#define CHECKFAIL(count) ((count)==0 && noneofthem())
/***************************************
* This is the most useful function in
* the program: it build an array
* of data characters in order to run
* several protocols on the returned
* data.
*/
int eventlist(int fd, char *buff, int buflen, int test, int readstep)
{
fd_set selSet, readySet;
struct timeval to;
int active=0;
int pending;
int got=0;
FD_ZERO(&readySet);
FD_SET(fd,&readySet);
FD_SET(fileno(stdin),&readySet);
to.tv_sec=to.tv_usec=0;
switch(test) {
case GPM_B_LEFT:
printf("\r\nNow please press and release several times\r\n"
"the left button of your mouse,"
" *** trying not to move it ***\r\n\r\n");
break;
case GPM_B_MIDDLE:
printf("\r\nNow please press and release several times\r\n"
"the middle button of your mouse,"
" *** trying not to move it ***\r\n\r\n");
break;
case 0:
printf("\r\nNow please move the mouse around, without pressing any\r\n"
"button. Move it both quickly and slowly\r\n\r\n");
break;
default:
printf("Unknown test to perform\r\n");
return -1;
}
printf("Press any key when you've done enough\r\n");
while(1) {
selSet=readySet;
if ((pending=select(fd+1,&selSet,NULL,NULL,&to)) < 0) continue;
if (pending==0 && !active) {
active++;
to.tv_sec=10;
continue;
}
if (pending==0) return got; /* timeout */
if (FD_ISSET(0,&selSet)) {
getchar();
if (active) return got;
}
if (FD_ISSET(fd,&selSet)) {
if (active) got+=read(fd,buff+got,readstep);
else read(fd,buff,buflen);
}
if (got>buflen-readstep)
readstep=buflen-got;
if (readstep==0)
got--,readstep++; /* overwrite last char forever */
to.tv_sec=30;
}
}
/*-----------------------------------------------------------------------------
Place the description here.
-----------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
struct item *list=NULL;
struct item **nextitem;
struct device *devlist=NULL;
struct device **nextdev;
Gpm_Type *cursor;
int i, mousefd;
char *mousename;
#define BUFLEN 512
char buf[BUFLEN];
struct timeval timeout;
fd_set checkSet;
int pending, maxfd;
int trial, readamount,packetsize,got;
int baudtab[4]={1200,9600,4800,2400};
#define BAUD(i) (baudtab[(i)%4])
consolename = Gpm_get_console();
if (!isatty(fileno(stdin))) {
fprintf(stderr,"%s: stdin: not a tty\n",argv[0]);
exit(1);
}
progname=argv[0];
message();
/* init the list of possible devices */
for (nextdev=&devlist, i=1; i<argc; i++)
nextdev=gpm_makedev(nextdev,argv[i]);
if (argc==1) { /* no cmdline, get all devices */
FILE *f;
char s[64];
/* Skip 10, 130 (== watchdog) to avoid causing spontaneous reboots */
f=popen("ls -l /dev/* | "
"awk '/^c/ && $5==\"10,\" && $6!=\"130\" || $NF ~ \"ttyS[0-3]$\" {print $NF}'",
"r");
if (!f) gpm_report(GPM_PR_OOPS,"popen()");
while (fgets(s,64,f)) {
s[strlen(s)-1]='\0'; /* trim '\n' */
nextdev=gpm_makedev(nextdev,s);
}
pclose(f);
}
if (devcount==0) {
fprintf(stderr,"%s: no devices found\n",progname);
exit(1);
}
I_serial=mice->init; /* the first one has I_serial */
signal(SIGINT,killed); /* control-C kills us */
raw();
/*====================================== First of all, detect the device */
trial=0;
while (devcount > 1) {
fd_set devSet, gotSet,savSet;
struct device *cur;
int gotthem;
/* BUG */ /* Logitech initialization is not performed */
(which_mouse->opt_baud)=BAUD(trial);
printf("\r\nTrying with %i baud\r\n",(which_mouse->opt_baud));
trial++;
FD_ZERO(&devSet); FD_ZERO(&gotSet);
FD_SET(fileno(stdin),&devSet); maxfd=fileno(stdin);
printf("\r\n The possible device nodes are:\r\n");
for (nextdev=&devlist; *nextdev; nextdev=&((*nextdev)->next)) {
printf("\t%s\r\n", (*nextdev)->name);
FD_SET((*nextdev)->fd,&devSet);
maxfd=max((*nextdev)->fd,maxfd);
(*I_serial)((*nextdev)->fd,(mice+1)->flags,mice+1,
1, &(mice+1)->name); /* try ms mode */
}
savSet=devSet;
printf("\r\n\r\nI've still %i devices which may be your mouse,\r\n",
devcount);
printf("Please move the mouse. Press any key when done\r\n"
" (You can specify your device name on cmdline, in order to\r\n"
" avoid this step\r\n. Different baud rates are tried at "
"different times\r\n");
timeout.tv_sec=10; /* max test time */
gotthem=0;
while (1) { /* extract files from the list */
devSet=savSet;
if ((pending=select(maxfd+1,&devSet,NULL,NULL,&timeout)) < 0)
continue;
if (pending==0 || FD_ISSET(fileno(stdin),&devSet)) {
getchar();
break;
}
for (nextdev=&devlist; *nextdev; nextdev=&((*nextdev)->next))
if (FD_ISSET((*nextdev)->fd,&devSet)) {
gotthem++;
FD_CLR((*nextdev)->fd,&savSet);
FD_SET((*nextdev)->fd,&gotSet);
}
}
if (gotthem) for (nextdev=&devlist; *nextdev; /* nothing */ ) {
cur=*nextdev;
if (!FD_ISSET(cur->fd,&gotSet)) {
printf("removing \"%s\" from the list\r\n",cur->name);
*nextdev=cur->next;
close(cur->fd);
free(cur->name);
free(cur);
devcount--;
} else {
read(cur->fd,buf,80); /* flush */
nextdev=&(cur->next); /* follow list */
}
}
} /* devcount>1 */
mousefd=devlist->fd;
mousename=devlist->name;
free(devlist);
printf("\r\nOk, so your mouse device is \"%s\"\r\n",mousename);
/* now close and reopen it, complete with initialization */
(which_mouse->opt_baud)=BAUD(0);
mousefd=mousereopen(mousefd,mousename,NULL);
FD_ZERO(&checkSet);
FD_SET(mousefd,&checkSet);
FD_SET(fileno(stdin),&checkSet);
maxfd=max(mousefd,fileno(stdin));
/*====================================== Identify mouse type */
/* init the list of possible types */
printf("\r\n\r\nThe possible mouse types are:\r\n");
for (nextitem=&list, cursor=mice; cursor->fun; cursor++) {
if (cursor->absolute) continue;
*nextitem=malloc(sizeof(struct item));
if (!*nextitem) gpm_report(GPM_PR_OOPS,"malloc()");
(*nextitem)->this=cursor; (*nextitem)->next=NULL;
printf("\t%s",cursor->name);
if (cursor->synonyms && cursor->synonyms[0])
printf(" (%s)",cursor->synonyms);
printf("\r\n");
typecount++;
nextitem=&((*nextitem)->next);
}
/*====================================== Packet size - first step */
printf("\r\nNow please press and release your left mouse button,\r\n"
"one time only\r\n\r\n");
i=read(mousefd,buf,1);
if (i==-1 && errno==EINVAL)
readamount=3;
else
readamount=1;
usleep(100000);
#define REMOVETYPE(cur,reason) \
do { \
printf("\tRemoving type \"%s\" because of '%s'\r\n", \
(cur)->this->name,reason); \
(*nextitem)=(cur)->next; \
free(cur); \
typecount--; \
} while(0)
for (nextitem=&list; *nextitem; /* nothing */) {
struct item *cur=*nextitem;
if (readamount!=cur->this->howmany)
REMOVETYPE(cur,"different read() semantics");
else
nextitem=&(cur->next);
}
read(mousefd,buf,BUFLEN); /* flush */
/*====================================== Packet size - second step */
printf("\r\nNow you will be asked to generate different kind of events,\r\n"
"in order to understand what protocol is your mouse speaking\r\n");
if (readamount==1) readamount=10;
/*
* Otherwise, the packetsize is already known, but the different decoding
* alghorithm allows for further refinement.
*/
packetsize=1;
trial=0;
while (packetsize==1) {
int success3=0,success5=0;
(which_mouse->opt_baud)=BAUD(trial);
printf("\tBaud rate is %i\r\n",(which_mouse->opt_baud));
mousefd=mousereopen(mousefd,mousename,NULL);
printf("\r\n==> Detecting the packet size\r\n");
got=eventlist(mousefd,buf,BUFLEN,GPM_B_LEFT,readamount);
/* try three -- look at repeating arrays of 6 bytes */
for (i=0;i<got-12;i++)
if(!memcmp(buf+i,buf+i+6,6))
success3++;
/* try five -- look at repeating arrays of 10 bytes */
for (i=0;i<got-20;i++)
if(!memcmp(buf+i,buf+i+10,10))
success5++;
printf("matches for 3 bytes: %i -- matches for 5 bytes: %i\r\n",
success3,success5);
if (success3>5 && success5==0)
packetsize=3;
if (success5>5 && success3==0)
packetsize=5;
if (packetsize==1)
printf("\r\n ** Ambiguous, try again\r\n");
trial++;
}
/*====================================== Use that info to discard protocols */
for (nextitem=&list; *nextitem; /* nothing */) {
struct item *cur=*nextitem;
int packetheads=0;
int match=0;
Gpm_Event event;
if (packetsize!=cur->this->packetlen) {
REMOVETYPE(cur,"different packet lenght");
continue;
}
/* try to decode button press and release */
for (i=0;i<got;i++) {
if ( ((buf[i] &(cur->this->proto)[0]) == (cur->this->proto)[1])
&& ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) {
packetheads++;
if ((*(cur->this->fun))(&event,buf+i)==-1) {
packetheads--;
continue;
}
i+=packetsize-1; /* skip packet */
if (event.dx || event.dy) continue;
if (event.buttons==GPM_B_LEFT)
match++;
else if (event.buttons)
match--;
}
}
if (match<=0) {
REMOVETYPE(cur,"incorrect button detected");
continue;
}
if (packetheads<got/(packetsize+2)) {
REMOVETYPE(cur,"too few events got decoded");
continue;
}
printf("** type '%s' still possible\r\n",cur->this->name);
nextitem=&(cur->next);
}
/*====================================== It's all done? */
/*
* At this point, msc, would be unique (and 3-button aware) due to the
* packet size; sun,mm and ps2 would be unique due to the different
* representation of buttons (and they usually are not dual mode).
*/
/* why checking and not using return value ??? */
CHECKFAIL(typecount);
if (typecount==1) {
noraw();
printf("\n\n\nWell, it seems like your mouse is already detected:\n"
"it is on the device \"%s\", and speaks the protocol \"%s\"\n",
mousename,list->this->name);
exit(0);
}
/*
* If it is in the "ms" family, however, three possibilities are still
* there, and all of them depend on the middle button
*/
do {
printf("\r\nYour mouse is one of the ms family, "
"but do you have the middle button (y/n)? ");
putchar(i=getchar()); printf("\r\n");
} while(i!='y' && i!='n');
if (i=='n') {
noraw();
printf("\nThen, you should use the \"bare\" protocol on \"%s\"\n",
mousename);
exit(0);
}
/*
* First trial: remove the "-t ms" extension if spurious buttons come in
*/
got=eventlist(mousefd,buf,BUFLEN,0,readamount);
pending=0;
for (nextitem=&list; *nextitem; /* nothing */) {
struct item *cur=*nextitem;
Gpm_Event event;
/* try to decode button press and release */
for (i=0;i<got;i++) {
if ( ((buf[i] &(cur->this->proto)[0]) == (cur->this->proto)[1])
&& ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) {
if ((*(cur->this->fun))(&event,buf+i)==-1) continue;
i+=packetsize-1;
if (event.buttons) pending--;
}
}
if (pending<0) {
REMOVETYPE(cur,"spurious button reported");
continue;
}
printf("** type '%s' still possible\r\n",cur->this->name);
nextitem=&(cur->next);
}
CHECKFAIL(typecount);
/*
* Second trial: look if it is one of the two mman ways (In the second
* test, extended ms is caught as well
*/
printf("\r\n==> Looking for '-t mman'and enhanced ms\r\n");
mousefd=mousereopen(mousefd,mousename, mice /* mman */);
got=eventlist(mousefd,buf,BUFLEN,GPM_B_MIDDLE,readamount);
/* if it uses the 4-byte protocol, find it in a rude way */
for (pending=0,i=0;i<got-16;i++)
if(!memcmp(buf+i,buf+i+8,8)) pending++;
if (pending > 3) {
noraw();
printf("\nYour mouse seems to be a 'mman' one on \"%s\" (%i matches)\n",
mousename,pending);
exit(0);
}
pending=0;
for (nextitem=&list; *nextitem; /* nothing */) {
struct item *cur=*nextitem;
Gpm_Event event;
/* try to decode button press and release */
for (i=0;i<got;i++) {
if ( ((buf[i] &(cur->this->proto)[0]) == (cur->this->proto)[1])
&& ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) {
if ((*(cur->this->fun))(&event,buf+i)==-1) continue;
i+=packetsize-1;
if (event.buttons && event.buttons!=GPM_B_MIDDLE) pending--;
if (event.buttons==GPM_B_MIDDLE) pending++;
}
}
if (pending<0) {
REMOVETYPE(cur,"spurious button reported");
continue;
}
if (pending>3) {
noraw();
printf("\nYour mouse seems to be a '%s' one on \"%s\" (%i matches)\n",
cur->this->name,mousename,pending);
exit(0);
}
printf("** type '%s' still possible\r\n",cur->this->name);
nextitem=&(cur->next);
}
CHECKFAIL(typecount);
/*
* Then, try to toggle dtr and rts
*/
{
int toggle[3]={TIOCM_DTR|TIOCM_RTS, TIOCM_DTR,TIOCM_RTS};
char *tognames[3]={"both","dtr","rts"};
char *Xtognames[3]={"'ClearDTR' and 'ClearRTS'","'ClearDTR'","'ClearRTS'"};
int alllines,lines, index;
ioctl(mousefd, TIOCMGET, &alllines);
printf("\r\nSome mice change protocol to three-buttons-aware if some\r\n"
"\r\ncontrol lines are toggled after opening\r\n");
for (index=0;index<3;index++) {
mousereopen(mousefd,mousename,NULL);
lines = alllines & ~toggle[index];
ioctl(mousefd, TIOCMSET, &lines);
printf("\r\n==> Trying with '-o %s'\r\n",tognames[index]);
got=eventlist(mousefd,buf,BUFLEN,GPM_B_MIDDLE,readamount);
/* if it uses the 5-byte protocol, find it in a rude way */
for (pending=0,i=0;i<got-20;i++)
if(!memcmp(buf+i,buf+i+10,10)) pending++;
if (pending>3) {
noraw();
printf("\nYour mouse becomes a 3-buttons ('-t msc') one when\n"
"gpm gets '-o %s' on it command line, and X gets\n"
"%s in XF86Config\nThe device is \"%s\"",
tognames[index],Xtognames[index],mousename);
exit(0);
}
}
}
/*
* still here? Then, the only resort is keeping the middle button
* pressed while initializing the mouse
*/
printf("\r\nYour damned device doesn't respond to anything\r\n"
"the only remaining possibility is to keep presses the middle\r\n"
"button _while_the_mouse_is_being_opened. This is the worst thing\r\n"
"ever thought after caps-lock-near-the-A\r\n");
printf("\r\nNow please press the middle button, and then press any key\r\n"
"while keeping the button down. Wait to release it until the\r\n"
"next message.\r\n");
getchar();
got=eventlist(mousefd,buf,BUFLEN,GPM_B_MIDDLE,readamount);
/* if it uses the 5-byte protocol, find it in a rude way */
for (pending=0,i=0;i<got-20;i++)
if(!memcmp(buf+i,buf+i+10,10)) pending++;
if (pending>3) {
noraw();
printf("\nWorked. You should keep the button pressed every time the\n"
"computer boots, and run gpm in '-R' mode in order to ignore\n"
"such hassle when starting X\n\nStill better, but a better mouse\n"
"\nThe current mouse device is \"%s\"\n",mousename);
exit(0);
}
noraw();
printf("\nI'm lost. Can't tell you how to use your middle button\n");
return 0;
}

View file

@ -0,0 +1,32 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
********/
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include <fcntl.h>
int open_console(const int mode)
{
int fd;
if ((fd = open(option.consolename, mode)) < 0)
gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, option.consolename);
return fd;
}