[gpm] [PATCH 17/18] liblow-cleanup.patch
Dmitry Torokhov
dtor_core@ameritech.net
Tue Aug 10 09:03:18 CEST 2004
===================================================================
ChangeSet@1.21, 2004-08-10 01:04:25-05:00, dtor_core@ameritech.net
liblow cleanup - split into smaller functions, fixed some memory
leaks in Gpm_Open.
liblow.c | 885 ++++++++++++++++++++++++++++++++-------------------------------
1 files changed, 461 insertions(+), 424 deletions(-)
===================================================================
diff -Nru a/src/lib/liblow.c b/src/lib/liblow.c
--- a/src/lib/liblow.c 2004-08-10 01:18:01 -05:00
+++ b/src/lib/liblow.c 2004-08-10 01:18:01 -05:00
@@ -1,11 +1,11 @@
-/*
- *
+/*
* liblow.c - client library - low level (gpm)
*
* Copyright 1994,1995 rubini@linux.it (Alessandro Rubini)
* Copyright (C) 1998 Ian Zimmerman <itz@rahul.net>
- * Copyright 2001 Nico Schottelius (nico@schottelius.org)
- *
+ * Copyright 2001 Nico Schottelius (nico-gpm@schottelius.org)
+ * Copyright 2004 Dmitry Torokhov <dtor@mail.ru>
+ *
* xterm management is mostly by jtklehto@stekt.oulu.fi (Janne Kukonlehto)
*
* This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#include <sys/ioctl.h>
#endif
-#include <signal.h>
+#include <signal.h>
#include <linux/vt.h> /* VT_GETSTATE */
#include <sys/kd.h> /* KDGETMODE */
#include <termios.h> /* winsize */
@@ -61,129 +61,239 @@
} Gpm_Stst;
/*....................................... Global variables */
-int gpm_flag=0; /* almost unuseful now -- where was it used for ? can
- we remove it now ? FIXME */
-int gpm_tried=0;
-int gpm_fd=-1;
-int gpm_hflag=0;
-Gpm_Stst *gpm_stack=NULL;
-struct timeval gpm_timeout={10,0};
-Gpm_Handler *gpm_handler=NULL;
-void *gpm_data=NULL;
-int gpm_zerobased=0;
-int gpm_visiblepointer=0;
+int gpm_flag; /* Open connections count */
+int gpm_tried;
+int gpm_fd = -1;
+int gpm_hflag;
+Gpm_Stst *gpm_stack;
+struct timeval gpm_timeout = {10, 0};
+Gpm_Handler *gpm_handler;
+void *gpm_data;
+int gpm_zerobased;
+int gpm_visiblepointer;
int gpm_mx, gpm_my; /* max x and y (1-based) to fit margins */
-unsigned char _gpm_buf[6*sizeof(short)];
-unsigned short * _gpm_arg = (unsigned short *)_gpm_buf +1;
+unsigned char _gpm_buf[6 * sizeof(short)];
+unsigned short * _gpm_arg = (unsigned short *)_gpm_buf + 1;
-int gpm_consolefd=-1; /* used to invoke ioctl() */
-int gpm_morekeys=0;
+int gpm_consolefd = -1; /* used to invoke ioctl() */
+int gpm_morekeys;
int gpm_convert_event(unsigned char *mdata, Gpm_Event *ePtr);
/*----------------------------------------------------------------------------*
* nice description
*----------------------------------------------------------------------------*/
-static inline int putdata(int where, Gpm_Connect *what)
+static inline int putdata(int where, Gpm_Connect *what)
{
#ifdef GPM_USE_MAGIC
- static int magic=GPM_MAGIC;
+ static int magic = GPM_MAGIC;
- if (write(where,&magic,sizeof(int))!=sizeof(int)) {
- gpm_report(GPM_PR_ERR,GPM_MESS_WRITE_ERR,strerror(errno));
+ if (write(where, &magic, sizeof(int)) != sizeof(int)) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_WRITE_ERR, strerror(errno));
return -1;
- }
+ }
#endif
- if (write(where,what,sizeof(Gpm_Connect))!=sizeof(Gpm_Connect))
- {
- gpm_report(GPM_PR_ERR,GPM_MESS_WRITE_ERR,strerror(errno));
+ if (write(where,what,sizeof(Gpm_Connect))!=sizeof(Gpm_Connect)) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_WRITE_ERR, strerror(errno));
return -1;
- }
- return 0;
+ }
+ return 0;
}
-#if (defined(SIGWINCH))
-/* itz Wed Mar 18 11:19:52 PST 1998 hook window change as well */
-
-/* Old SIGWINCH handler. */
+static void get_screen_dimensions(void)
+{
+ struct winsize win;
-static struct sigaction gpm_saved_winch_hook;
+ if (ioctl(gpm_consolefd, TIOCGWINSZ, &win) == 0) {
+ if (!win.ws_col || !win.ws_row) {
+ win.ws_col = 80;
+ win.ws_row = 25;
+ }
+ gpm_mx = win.ws_col - gpm_zerobased;
+ gpm_my = win.ws_row - gpm_zerobased;
+ }
+}
/*----------------------------------------------------------------------------*
* nice description
*----------------------------------------------------------------------------*/
+#if defined(SIGWINCH)
+
+static struct sigaction gpm_saved_winch_hook; /* Old SIGWINCH handler. */
static void gpm_winch_hook (int signum)
{
- struct winsize win;
+ if (SIG_IGN != gpm_saved_winch_hook.sa_handler &&
+ SIG_DFL != gpm_saved_winch_hook.sa_handler) {
+ gpm_saved_winch_hook.sa_handler(signum);
+ }
- if (SIG_IGN != gpm_saved_winch_hook.sa_handler &&
- SIG_DFL != gpm_saved_winch_hook.sa_handler) {
- gpm_saved_winch_hook.sa_handler(signum);
- } /*if*/
- if (ioctl(gpm_consolefd, TIOCGWINSZ, &win) == -1) {
- return;
- } /*if*/
- if (!win.ws_col || !win.ws_row) {
- win.ws_col=80; win.ws_row=25;
- } /*if*/
- gpm_mx = win.ws_col - gpm_zerobased;
- gpm_my = win.ws_row - gpm_zerobased;
+ get_screen_dimensions();
}
-#endif /* SIGWINCH */
+static void install_winch_hook(void)
+{
+ struct sigaction sa;
-#if (defined(SIGTSTP))
-/* itz: support for SIGTSTP */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = gpm_winch_hook;
+ sa.sa_flags = 0;
+ sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
+}
-/* Old SIGTSTP handler. */
+static void remove_winch_hook(void)
+{
+ sigaction(SIGWINCH, &gpm_saved_winch_hook, 0);
+}
-static struct sigaction gpm_saved_suspend_hook;
+#else
+#define install_winch_hook() /* nothing */
+#define remove_winch_hook() /* nothing */
+#endif /* SIGWINCH */
/*----------------------------------------------------------------------------*
* nice description
*----------------------------------------------------------------------------*/
-static void gpm_suspend_hook (int signum)
+#if defined(SIGTSTP)
+
+static struct sigaction gpm_saved_suspend_hook;
+
+static void gpm_suspend_hook(int signum)
+{
+ Gpm_Connect gpm_connect;
+ sigset_t old_sigset;
+ sigset_t new_sigset;
+ struct sigaction sa;
+ int success;
+
+ sigemptyset(&new_sigset);
+ sigaddset(&new_sigset, SIGTSTP);
+ sigprocmask(SIG_BLOCK, &new_sigset, &old_sigset);
+
+ /* Open a completely transparent gpm connection */
+ gpm_connect.eventMask = 0;
+ gpm_connect.defaultMask = ~0;
+ gpm_connect.minMod = ~0;
+ gpm_connect.maxMod = 0;
+ /* cannot do this under xterm, tough */
+ success = (Gpm_Open(&gpm_connect, 0) >= 0);
+
+ /* take the default action, whatever it is (probably a stop :) */
+ sigprocmask(SIG_SETMASK, &old_sigset, 0);
+ sigaction(SIGTSTP, &gpm_saved_suspend_hook, 0);
+ kill(getpid(), SIGTSTP);
+
+ /* in bardo here */
+
+ /* Reincarnation. Prepare for another death early. */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = gpm_suspend_hook;
+ sa.sa_flags = SA_NOMASK;
+ sigaction(SIGTSTP, &sa, 0);
+
+ /* Pop the gpm stack by closing the useless connection */
+ /* but do it only when we know we opened one.. */
+ if (success)
+ Gpm_Close();
+}
+
+static void install_suspend_hook(void)
+{
+ struct sigaction sa;
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTSTP, &sa, &gpm_saved_suspend_hook);
+
+ /* if signal was originally ignored, job control is not supported */
+ if (gpm_saved_suspend_hook.sa_handler != SIG_IGN) {
+ sa.sa_flags = SA_NOMASK;
+ sa.sa_handler = gpm_suspend_hook;
+ sigaction(SIGTSTP, &sa, 0);
+ }
+}
+
+static void remove_suspend_hook(void)
{
- Gpm_Connect gpm_connect;
- sigset_t old_sigset;
- sigset_t new_sigset;
- struct sigaction sa;
- int success;
-
- sigemptyset (&new_sigset);
- sigaddset (&new_sigset, SIGTSTP);
- sigprocmask (SIG_BLOCK, &new_sigset, &old_sigset);
-
- /* Open a completely transparent gpm connection */
- gpm_connect.eventMask = 0;
- gpm_connect.defaultMask = ~0;
- gpm_connect.minMod = ~0;
- gpm_connect.maxMod = 0;
- /* cannot do this under xterm, tough */
- success = (Gpm_Open (&gpm_connect, 0) >= 0);
-
- /* take the default action, whatever it is (probably a stop :) */
- sigprocmask (SIG_SETMASK, &old_sigset, 0);
- sigaction (SIGTSTP, &gpm_saved_suspend_hook, 0);
- kill (getpid (), SIGTSTP);
-
- /* in bardo here */
-
- /* Reincarnation. Prepare for another death early. */
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = gpm_suspend_hook;
- sa.sa_flags = SA_NOMASK;
- sigaction (SIGTSTP, &sa, 0);
-
- /* Pop the gpm stack by closing the useless connection */
- /* but do it only when we know we opened one.. */
- if (success) {
- Gpm_Close ();
- } /*if*/
+ sigaction(SIGTSTP, &gpm_saved_suspend_hook, 0);
}
+
+#else
+#define install_suspend_hook() /* nothing */
+#define remove_suspend_hook() /* nothing */
#endif /* SIGTSTP */
+static int open_server_socket(void)
+{
+ struct sockaddr_un addr;
+ char *sock_name = NULL;
+ int fd;
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_SOCKET, strerror(errno));
+ return -1;
+ }
+
+#ifndef SO_PEERCRED
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (!(sock_name = tempnam(0, "gpm"))) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_TEMPNAM, strerror(errno));
+ goto err;
+ }
+ strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path));
+ if (bind(fd, (struct sockaddr *)&addr,
+ sizeof(addr.sun_family) + strlen(addr.sun_path)) == -1) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_DOUBLE_S, sock_name, strerror(errno));
+ goto err;
+ }
+#endif
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, GPM_NODE_CTL);
+
+ if (connect(fd, (struct sockaddr *)&addr,
+ sizeof(addr.sun_family) + strlen(GPM_NODE_CTL)) < 0) {
+ gpm_report(GPM_PR_INFO, GPM_MESS_DOUBLE_S, GPM_NODE_CTL, strerror(errno));
+ goto err;
+ }
+
+ return fd;
+
+ err:
+ close(fd);
+ if (sock_name) {
+ unlink(sock_name);
+ free(sock_name);
+ }
+
+ return -1;
+}
+
+static int open_server_device(void)
+{
+ struct stat stbuf;
+ int fd;
+
+ /*
+ * Well, try to open a chr device called /dev/gpmctl. This should
+ * be forward-compatible with a kernel server
+ */
+ if ((fd = open(GPM_NODE_DEV, O_RDWR)) == -1) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_DOUBLE_S, GPM_NODE_DEV, strerror(errno));
+ return -1;
+ }
+
+ if (fstat(fd, &stbuf) == -1 || (stbuf.st_mode & S_IFMT) != S_IFCHR) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+
/*----------------------------------------------------------------------------*
* nice description
*----------------------------------------------------------------------------*/
@@ -192,28 +302,22 @@
static char *console_name;
static int console_queried;
- char *tty = NULL;
- char *term = NULL;
- int i;
- struct sockaddr_un addr;
- struct winsize win;
- Gpm_Stst *new = NULL;
- char* sock_name = 0;
-
- gpm_report(GPM_PR_DEBUG,"VC: %d",flag);
+ char *tty = NULL, *tty_str = NULL;
+ char *term;
+ Gpm_Stst *new;
/*....................................... First of all, check xterm */
- if ((term=(char *)getenv("TERM")) && !strncmp(term,"xterm",5)) {
- if(gpm_tried) return gpm_fd; /* no stack */
- gpm_fd=-2;
+ if ((term = getenv("TERM")) && !strncmp(term, "xterm", 5)) {
+ gpm_fd = -2;
GPM_XTERM_ON;
- gpm_flag=1;
+ gpm_flag = 1;
return gpm_fd;
}
- /*....................................... No xterm, go on */
- /* check whether we know what name the console is: what's with the lib??? */
+ /*....................................... Not a xterm, go on */
+
+ /* check whether console is accesible */
if (!console_queried) {
console_name = Gpm_get_console();
console_queried = 1;
@@ -234,227 +338,156 @@
* However, making this piece of code work has been a real hassle.
*/
- if (!gpm_flag && gpm_tried) return -1;
- gpm_tried=1; /* do or die */
-
- if ((new = (Gpm_Stst *) malloc(sizeof(Gpm_Stst))) == NULL)
+ if (!gpm_flag && gpm_tried)
return -1;
- new->next=gpm_stack;
- gpm_stack=new;
+ gpm_tried = 1; /* do or die */
- conn->pid =getpid(); /* fill obvious values */
+ if ((new = malloc(sizeof(Gpm_Stst))) == NULL) {
+ gpm_report(GPM_PR_ERR, "Not enough memory for a new connection");
+ return -1;
+ }
- if (new->next)
- conn->vc=new->next->info.vc; /* inherit */
- else {
- conn->vc=0; /* default handler */
+ conn->pid = getpid(); /* fill obvious values */
+
+ if (gpm_stack) {
+ conn->vc = new->next->info.vc; /* inherit */
+ } else {
+ conn->vc = 0; /* default handler */
if (flag > 0) { /* forced vc number */
- conn->vc=flag;
- if ((tty = malloc(strlen(console_name) + Gpm_cnt_digits(flag))) == NULL)
- gpm_report(GPM_PR_OOPS, GPM_MESS_NO_MEM);
- memcpy(tty, console_name, strlen(console_name)-1);
+ conn->vc = flag;
+ tty = tty_str = malloc(strlen(console_name) + Gpm_cnt_digits(flag));
+ if (!tty) {
+ gpm_report(GPM_PR_ERR, "Not enough memory for tty name");
+ goto err;
+ }
+ memcpy(tty, console_name, strlen(console_name) - 1);
sprintf(&tty[strlen(console_name) - 1], "%i", flag);
} else { /* use your current vc */
if (isatty(0)) tty = ttyname(0); /* stdin */
if (!tty && isatty(1)) tty = ttyname(1); /* stdout */
if (!tty && isatty(2)) tty = ttyname(2); /* stderr */
- if (tty == NULL) {
- gpm_report(GPM_PR_ERR,"checking tty name failed");
+ if (!tty) {
+ gpm_report(GPM_PR_ERR, "Checking tty name failed");
goto err;
}
- /* do we really need this check ? */
- if (strncmp(tty, console_name, strlen(console_name) - 1)
- || !isdigit(tty[strlen(console_name) - 1])) {
- gpm_report(GPM_PR_ERR, "strncmp/isdigit/consolename failed");
+
+ /* Make sure that we actually running aon console */
+ if (strncmp(tty, console_name, strlen(console_name) - 1) ||
+ !isdigit(tty[strlen(console_name) - 1])) {
+ gpm_report(GPM_PR_DEBUG, "Not running on local console");
goto err;
}
conn->vc = atoi(&tty[strlen(console_name) - 1]);
}
- if (gpm_consolefd == -1)
- if ((gpm_consolefd=open(tty,O_WRONLY)) < 0) {
- gpm_report(GPM_PR_ERR,GPM_MESS_DOUBLE_S,tty,strerror(errno));
+ if (gpm_consolefd == -1) {
+ if ((gpm_consolefd = open(tty, O_WRONLY)) < 0) {
+ gpm_report(GPM_PR_ERR, GPM_MESS_DOUBLE_S, tty, strerror(errno));
goto err;
}
+ }
}
- new->info=*conn;
-
- /*....................................... Get screen dimensions */
+ new->info = *conn;
- ioctl(gpm_consolefd, TIOCGWINSZ, &win);
-
- if (!win.ws_col || !win.ws_row) {
- fprintf(stderr, "libgpm: zero screen dimension, assuming 80x25.\n");
- win.ws_col=80; win.ws_row=25;
- }
- gpm_mx = win.ws_col - gpm_zerobased;
- gpm_my = win.ws_row - gpm_zerobased;
+ get_screen_dimensions();
/*....................................... Connect to the control socket */
- if (!(gpm_flag++)) {
- if ( (gpm_fd=socket(AF_UNIX,SOCK_STREAM,0))<0 ) {
- gpm_report(GPM_PR_ERR,GPM_MESS_SOCKET,strerror(errno));
- goto err;
- }
-
-#ifndef SO_PEERCRED
- bzero((char *)&addr,sizeof(addr));
- addr.sun_family=AF_UNIX;
- if (!(sock_name = tempnam (0, "gpm"))) {
- gpm_report(GPM_PR_ERR,GPM_MESS_TEMPNAM,strerror(errno));
- goto err;
- }
- strncpy (addr.sun_path, sock_name, sizeof (addr.sun_path));
- if (bind (gpm_fd, (struct sockaddr*)&addr,
- sizeof (addr.sun_family) + strlen (addr.sun_path))==-1) {
- gpm_report(GPM_PR_ERR,GPM_MESS_DOUBLE_S, sock_name, strerror(errno));
- goto err;
- }
-#endif
-
- bzero((char *)&addr,sizeof(addr));
- addr.sun_family=AF_UNIX;
- strcpy(addr.sun_path, GPM_NODE_CTL);
- i=sizeof(addr.sun_family)+strlen(GPM_NODE_CTL);
-
- if(connect(gpm_fd,(struct sockaddr *)(&addr),i)<0 ) {
- struct stat stbuf;
-
- gpm_report(GPM_PR_INFO,GPM_MESS_DOUBLE_S,GPM_NODE_CTL,strerror(errno));
- /*
- * Well, try to open a chr device called /dev/gpmctl. This should
- * be forward-compatible with a kernel server
- */
- close(gpm_fd); /* the socket */
- if ((gpm_fd=open(GPM_NODE_DEV,O_RDWR))==-1) {
- gpm_report(GPM_PR_ERR,GPM_MESS_DOUBLE_S,GPM_NODE_DEV
- ,strerror(errno));
- goto err;
- }
- if (fstat(gpm_fd,&stbuf)==-1 || (stbuf.st_mode&S_IFMT)!=S_IFCHR) {
+ if (!gpm_flag) {
+ if ((gpm_fd = open_server_socket()) < 0)
+ if ((gpm_fd = open_server_device()) < 0)
goto err;
- }
- }
}
- /*....................................... Put your data */
-
- if (putdata(gpm_fd,conn)!=-1) {
- /* itz Wed Dec 16 23:22:16 PST 1998 use sigaction, the old
- code caused a signal loop under XEmacs */
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
-
-#if (defined(SIGWINCH))
- /* And the winch hook .. */
- sa.sa_handler = gpm_winch_hook;
- sa.sa_flags = 0;
- sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
-#endif
-#if (defined(SIGTSTP))
- if (gpm_flag == 1) {
- /* Install suspend hook */
- sa.sa_handler = SIG_IGN;
- sigaction(SIGTSTP, &sa, &gpm_saved_suspend_hook);
-
- /* if signal was originally ignored, job control is not supported */
- if (gpm_saved_suspend_hook.sa_handler != SIG_IGN) {
- sa.sa_flags = SA_NOMASK;
- sa.sa_handler = gpm_suspend_hook;
- sigaction(SIGTSTP, &sa, 0);
- }
- }
-#endif
+ new->next = gpm_stack;
+ gpm_stack = new;
+ gpm_flag++;
+ /*....................................... Put your data */
+ if (putdata(gpm_fd, conn) != -1) {
+ install_winch_hook();
+ if (gpm_flag == 1) /* first open only */
+ install_suspend_hook();
}
+
return gpm_fd;
/*....................................... Error: free all memory */
- err:
- gpm_report(GPM_PR_ERR,"Oh, oh, it's an error! possibly I die! ");
- while (gpm_stack) {
- new=gpm_stack->next;
- free(gpm_stack);
- gpm_stack=new;
- }
- if (gpm_fd>=0) close(gpm_fd);
- if (sock_name) {
- unlink(sock_name);
- free(sock_name);
- sock_name = 0;
- }
- gpm_flag=0;
+ err:
+ free(new);
+ if (tty_str) free(tty_str);
+
return -1;
}
/*-------------------------------------------------------------------*/
int Gpm_Close(void)
{
- Gpm_Stst *next;
+ Gpm_Stst *next;
- gpm_tried=0; /* reset the error flag for next time */
- if (gpm_fd==-2) /* xterm */
- GPM_XTERM_OFF;
- else /* linux */
- {
- if (!gpm_flag) return 0;
- next=gpm_stack->next;
+ gpm_tried = 0; /* reset the error flag for next time */
+
+ if (gpm_fd == -2) /* xterm */
+ GPM_XTERM_OFF;
+ else { /* linux */
+ if (!gpm_flag)
+ return 0;
+ next = gpm_stack->next;
free(gpm_stack);
- gpm_stack=next;
+ gpm_stack = next;
if (next)
- putdata(gpm_fd,&(next->info));
+ putdata(gpm_fd, &next->info);
- if (--gpm_flag) return -1;
- }
+ if (--gpm_flag)
+ return -1;
+ }
- if (gpm_fd>=0) close(gpm_fd);
- gpm_fd=-1;
-#ifdef SIGTSTP
- sigaction(SIGTSTP, &gpm_saved_suspend_hook, 0);
-#endif
-#ifdef SIGWINCH
- sigaction(SIGWINCH, &gpm_saved_winch_hook, 0);
-#endif
- close(gpm_consolefd);
- gpm_consolefd=-1;
- return 0;
+ if (gpm_fd >= 0)
+ close(gpm_fd);
+ gpm_fd = -1;
+
+ remove_suspend_hook();
+ remove_winch_hook();
+
+ if (gpm_consolefd >= 0)
+ close(gpm_consolefd);
+ gpm_consolefd = -1;
+
+ return 0;
}
/*-------------------------------------------------------------------*/
int Gpm_GetEvent(Gpm_Event *event)
{
- int count;
- MAGIC_P((int magic));
+ int count;
+ MAGIC_P((int magic));
- if (!gpm_flag) return 0;
+ if (!gpm_flag)
+ return 0;
#ifdef GPM_USE_MAGIC
- if ((count=read(gpm_fd,&magic,sizeof(int)))!=sizeof(int))
- {
- if (count==0)
- {
+ if ((count = read(gpm_fd, &magic, sizeof(int))) != sizeof(int)) {
+ if (count == 0) {
gpm_report(GPM_PR_INFO,"Warning: closing connection");
Gpm_Close();
return 0;
- }
- gpm_report(GPM_PR_INFO,"Read too few bytes (%i) at %s:%d",count,__FILE__,__LINE__);
+ }
+ gpm_report(GPM_PR_INFO, "Read too few bytes (%i) at %s:%d",
+ count, __FILE__, __LINE__);
return -1;
- }
+ }
#endif
- if ((count=read(gpm_fd,event,sizeof(Gpm_Event)))!=sizeof(Gpm_Event))
- {
+ if ((count = read(gpm_fd, event, sizeof(Gpm_Event))) != sizeof(Gpm_Event)) {
#ifndef GPM_USE_MAGIC
- if (count==0)
- {
+ if (count == 0) {
gpm_report(GPM_PR_INFO,"Warning: closing connection");
Gpm_Close();
return 0;
- }
+ }
#endif
/*
* avoid to send the message if there is no data; sometimes it makes
@@ -462,211 +495,215 @@
* non-blocking descriptor
*/
if (count != -1 || errno != EAGAIN)
- gpm_report(GPM_PR_INFO,"Read too few bytes (%i) at %s:%d",
- count,__FILE__,__LINE__);
+ gpm_report(GPM_PR_INFO, "Read too few bytes (%i) at %s:%d",
+ count, __FILE__, __LINE__);
return -1;
- }
+ }
- event->x -= gpm_zerobased;
- event->y -= gpm_zerobased;
+ event->x -= gpm_zerobased;
+ event->y -= gpm_zerobased;
- return 1;
+ return 1;
}
#define MAXNBPREVCHAR 4 /* I don't think more is usefull, JD */
-static int nbprevchar=0, prevchar[MAXNBPREVCHAR];
+static int n_prevchar, prevchar[MAXNBPREVCHAR];
/*-------------------------------------------------------------------*/
int Gpm_CharsQueued ()
{
- return nbprevchar;
+ return n_prevchar;
+}
+
+/*-------------------------------------------------------------------*/
+int Gpm_WaitForData(int fd)
+{
+ struct timeval tmo = { SELECT_TIME, 0 };
+ static fd_set selSet;
+ int max_fd = (gpm_fd > fd) ? gpm_fd : fd;
+
+ do {
+ FD_ZERO(&selSet);
+ FD_SET(fd, &selSet);
+ if (gpm_fd >= 0)
+ FD_SET(gpm_fd, &selSet);
+
+ } while (select(max_fd + 1, &selSet, NULL, NULL, &tmo) <= 0);
+
+ return FD_ISSET(fd, &selSet) ? fd : gpm_fd;
+}
+
+/*-------------------------------------------------------------------*/
+int Gpm_WaitMoreData(int fd)
+{
+ struct timeval tmo = { 0, 100 * 1000 }; /* 100 msecs */
+ static fd_set selSet;
+ int rc;
+
+ FD_ZERO(&selSet);
+ FD_SET(fd, &selSet);
+
+ while ((rc = select(fd + 1, &selSet, NULL, NULL, &tmo)) == EINTR)
+ /* empty */;
+
+ return rc > 0;
}
/*-------------------------------------------------------------------*/
int Gpm_Getc(FILE *f)
{
- fd_set selSet;
- int max, flag, result;
- static Gpm_Event ev;
- int fd=fileno(f);
- static int count;
-
- /* Hmm... I must be sure it is unbuffered */
- if (!(count++))
- setvbuf(f,NULL,_IONBF,0);
-
- if (!gpm_flag) return getc(f);
-
- /* If the handler asked to provide more keys, give them back */
- if (gpm_morekeys) return (*gpm_handler)(&ev,gpm_data);
- gpm_hflag=0;
-
- max = (gpm_fd>fd) ? gpm_fd : fd;
-
- /*...................................................................*/
- if (gpm_fd>=0) /* linux */
- while(1)
- {
- if (gpm_visiblepointer) GPM_DRAWPOINTER(&ev);
- do
- {
- FD_ZERO(&selSet);
- FD_SET(fd,&selSet);
- if (gpm_fd>-1)
- FD_SET(gpm_fd,&selSet);
- gpm_timeout.tv_sec=SELECT_TIME;
- flag=select(max+1,&selSet,(fd_set *)NULL,(fd_set *)NULL,&gpm_timeout);
- }
- while (!flag);
-
- if (flag==-1)
- continue;
-
- if (FD_ISSET(fd,&selSet))
- return fgetc(f);
-
- if (Gpm_GetEvent(&ev) && gpm_handler
- && (result=(*gpm_handler)(&ev,gpm_data)))
- {
- gpm_hflag=1;
- return result;
- }
- }
- else
- /*...................................................................*/
- if (gpm_fd==-2) /* xterm */
- {
-#define DELAY_MS 100
- static struct timeval to={0,DELAY_MS*1000};
- static fd_set selSet;
- extern int gpm_convert_event(unsigned char *data, Gpm_Event *event);
- int c; unsigned char mdata[4];
-
- if (nbprevchar) /* if there are some consumed char ... */
- return prevchar[--nbprevchar];
-
- while(1)
- {
- do
- {
- FD_ZERO(&selSet); FD_SET(fd,&selSet);
- gpm_timeout.tv_sec=SELECT_TIME;
- flag=select(fd+1,&selSet,(fd_set *)NULL,(fd_set *)NULL,&gpm_timeout);
- }
- while (!flag);
-
- if ((c=fgetc(f))!=0x1b) return c;
-
- /* escape: go on */
- FD_ZERO(&selSet); FD_SET(fd,&selSet); to.tv_usec=DELAY_MS*1000;
- if ((flag=select(fd+1,&selSet,(fd_set *)NULL,(fd_set *)NULL,&to))==0)
- return c;
- if ((c=fgetc(f))!='[')
- {prevchar[nbprevchar++]=c; return 0x1B;} /* patche par JD 11/08/1998 */
-
- /* '[': go on */
- FD_ZERO(&selSet); FD_SET(fd,&selSet); to.tv_usec=DELAY_MS*1000;
- if ((flag=select(fd+1,&selSet,(fd_set *)NULL,(fd_set *)NULL,&to))==0)
- {prevchar[nbprevchar++]=c; return 0x1B;} /* patche par JD 11/08/1998 */
- if ((c=fgetc(f))!='M')
- /* patche par JD 11/08/1998 NOTICE: prevchar is a lifo !*/
- {prevchar[nbprevchar++]=c; prevchar[nbprevchar++]='['; return 0x1B;}
-
- /* now, it surely is a mouse event */
-
- for (c=0;c<3;c++) mdata[c]=fgetc(f);
- gpm_convert_event(mdata,&ev);
-
- if (gpm_handler && (result=(*gpm_handler)(&ev,gpm_data)))
- {
- gpm_hflag=1;
- return result;
- }
- } /* while(1) */
+ static Gpm_Event ev;
+ static int nbuf_set;
+
+ int fd = fileno(f);
+ char mdata[4];
+ int c, result;
+
+ /* Hmm... I must be sure it is unbuffered */
+ if (!nbuf_set) {
+ setvbuf(f, NULL, _IONBF, 0);
+ nbuf_set = 1;
+ }
+
+ if (!gpm_flag)
+ return getc(f);
+
+ /* If the handler asked to provide more keys, give them back */
+ if (gpm_morekeys)
+ return (*gpm_handler)(&ev, gpm_data);
+
+ gpm_hflag = 0;
+
+ if (n_prevchar) /* if there are some consumed char ... */
+ return prevchar[--n_prevchar];
+
+ while (1) {
+ if (gpm_fd >= 0 && gpm_visiblepointer)
+ GPM_DRAWPOINTER(&ev);
+
+ if (Gpm_WaitForData(fd) != fd) {
+ /* GPM is available (running on console), iget event from it */
+
+ if (!Gpm_GetEvent(&ev))
+ continue;
+
+ } else if (gpm_fd == -2) {
+ /* Running in Xterm, is it a mouse event or regular data? */
+
+ if ((c = fgetc(f)) != 0x1b)
+ return c;
+
+ /* escape: go on */
+ if (!Gpm_WaitMoreData(fd))
+ return c;
+
+ if ((c = fgetc(f)) != '[') {
+ prevchar[n_prevchar++] = c;
+ return 0x1B;
+ }
+
+ /* '[': go on */
+ if (!Gpm_WaitMoreData(fd)) {
+ prevchar[n_prevchar++] = c;
+ return 0x1B;
+ }
+
+ if ((c = fgetc(f)) != 'M') { /* NOTICE: prevchar is a lifo !*/
+ prevchar[n_prevchar++] = c;
+ prevchar[n_prevchar++] = '[';
+ return 0x1B;
+ }
+
+ /* now, it surely is a mouse event */
+ for (c = 0; c < 3; c++)
+ mdata[c] = fgetc(f);
+ gpm_convert_event(mdata, &ev);
+
+ } else {
+ /* Not running in Xterm and not GPM event, just read the data */
+ return fgetc(f);
}
- /*...................................................................*/
- else return fgetc(f); /* no mouse available */
+ /* Ok, we have a new event, handle it */
+ if (gpm_handler && (result = gpm_handler(&ev, gpm_data))) {
+ gpm_hflag = 1;
+ return result;
+ }
+ }
}
-
/*-------------------------------------------------------------------*/
int Gpm_Repeat(int msec)
{
- struct timeval to={0,1000*msec};
- int fd;
- fd_set selSet;
- fd=gpm_fd>=0 ? gpm_fd : 0; /* either the socket or stdin */
-
- FD_ZERO(&selSet);
- FD_SET(fd,&selSet);
- return (select(fd+1,&selSet,(fd_set *)NULL,(fd_set *)NULL,&to)==0);
+ struct timeval to = {0, 1000 * msec};
+ fd_set selSet;
+ int fd = gpm_fd >= 0 ? gpm_fd : 0; /* either the socket or stdin */
+
+ FD_ZERO(&selSet);
+ FD_SET(fd, &selSet);
+ return select(fd + 1, &selSet, NULL, NULL, &to) == 0;
}
/*-------------------------------------------------------------------*/
int Gpm_FitValuesM(int *x, int *y, int margin)
{
- if (margin==-1)
- {
- *x = min( max(*x,!gpm_zerobased), gpm_mx);
- *y = min( max(*y,!gpm_zerobased), gpm_my);
- return 0;
- }
- switch(margin)
- {
- case GPM_TOP: (*y)++; break;
- case GPM_BOT: (*y)--; break;
- case GPM_RGT: (*x)--; break;
- case GPM_LFT: (*x)++; break;
- }
- return 0;
+ switch (margin) {
+ case -1:
+ *x = min(max(*x, !gpm_zerobased), gpm_mx);
+ *y = min(max(*y, !gpm_zerobased), gpm_my);
+ break;
+
+ case GPM_TOP: (*y)++; break;
+ case GPM_BOT: (*y)--; break;
+ case GPM_RGT: (*x)--; break;
+ case GPM_LFT: (*x)++; break;
+ }
+ return 0;
}
/*-------------------------------------------------------------------*/
int gpm_convert_event(unsigned char *mdata, Gpm_Event *ePtr)
{
- static struct timeval tv1={0,0}, tv2;
- static int clicks=0;
- int c;
+ static struct timeval tv1, tv2;
+ static int clicks;
+ int c;
#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
#define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \
(t2.tv_usec-t1.tv_usec)/1000)
- /* Variable btn has following meaning: */
- c = mdata[0]-32; /* 0="1-down", 1="2-down", 2="3-down", 3="up" */
+ /* Variable btn has following meaning: */
+ c = mdata[0] - 32; /* 0="1-down", 1="2-down", 2="3-down", 3="up" */
- if (c==3)
- {
- ePtr->type = GPM_UP | (GPM_SINGLE<<clicks);
+ if (c == 3) {
+ ePtr->type = GPM_UP | (GPM_SINGLE << clicks);
/* ePtr->buttons = 0; */ /* no, keep info from press event */
- GET_TIME (tv1);
+ GET_TIME(tv1);
clicks = 0;
- }
- else
- {
+ } else {
ePtr->type = GPM_DOWN;
- GET_TIME (tv2);
- if (tv1.tv_sec && (DIF_TIME(tv1,tv2)<250)) /* 250ms for double click */
- {clicks++; clicks%=3;}
- else clicks = 0;
-
- switch (c)
- {
- case 0: ePtr->buttons=GPM_B_LEFT; break;
- case 1: ePtr->buttons=GPM_B_MIDDLE; break;
- case 2: ePtr->buttons=GPM_B_RIGHT; break;
- default: /* Nothing */ break;
- }
- }
- /* Coordinates are 33-based */
- /* Transform them to 1-based */
- ePtr->x = mdata[1]-32-gpm_zerobased;
- ePtr->y = mdata[2]-32-gpm_zerobased;
- return 0;
+ GET_TIME(tv2);
+ if (tv1.tv_sec && (DIF_TIME(tv1, tv2) < 250)) {
+ /* 250ms for double click */
+ clicks++; clicks %= 3;
+ } else
+ clicks = 0;
+
+ switch (c) {
+ case 0: ePtr->buttons = GPM_B_LEFT; break;
+ case 1: ePtr->buttons = GPM_B_MIDDLE; break;
+ case 2: ePtr->buttons = GPM_B_RIGHT; break;
+ default: /* Nothing */ break;
+ }
+ }
+ /* Coordinates are 33-based */
+ /* Transform them to 1-based */
+ ePtr->x = mdata[1] - 32 - gpm_zerobased;
+ ePtr->y = mdata[2] - 32 - gpm_zerobased;
+ return 0;
}
/* Local Variables: */
More information about the gpm
mailing list