=================================================================== ChangeSet@xxxx, 2004-08-10 01:04:25-05:00, dtor_core@xxxxxxxxxxxxx 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@xxxxxxxx (Alessandro Rubini) * Copyright (C) 1998 Ian Zimmerman <itz@xxxxxxxxx> - * Copyright 2001 Nico Schottelius (nico@xxxxxxxxxxxxxxx) - * + * Copyright 2001 Nico Schottelius (nico-gpm@xxxxxxxxxxxxxxx) + * Copyright 2004 Dmitry Torokhov <dtor@xxxxxxx> + * * xterm management is mostly by jtklehto@xxxxxxxxxxxxx (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: */ _______________________________________________ gpm mailing list gpm@xxxxxxxxxxxxxx http://lists.linux.it/listinfo/gpm