--- src/lib/liblow.c 2009-02-09 12:58:53.000000000 +0300 +++ src/lib/liblow.c 2009-09-06 22:33:11.000000000 +0400 @@ -77,7 +77,8 @@ int gpm_mx, gpm_my; /* max x and y (1-ba unsigned char _gpm_buf[6*sizeof(short)]; unsigned short * _gpm_arg = (unsigned short *)_gpm_buf +1; -int gpm_consolefd=-1; /* used to invoke ioctl() */ +enum { GPM_FD_INVALID = -1, GPM_FD_SCREEN = -2 }; +int gpm_consolefd = GPM_FD_INVALID; /* used to invoke ioctl() */ int gpm_morekeys=0; int gpm_convert_event(unsigned char *mdata, Gpm_Event *ePtr); @@ -121,7 +122,14 @@ static void gpm_winch_hook (int signum) SIG_DFL != gpm_saved_winch_hook.sa_handler) { gpm_saved_winch_hook.sa_handler(signum); } /*if*/ - if (ioctl(gpm_consolefd, TIOCGWINSZ, &win) == -1) { + if (GPM_FD_SCREEN == gpm_consolefd) { + /* TODO: */ + win.ws_col = 80; + win.ws_row = 25; + } else if (gpm_consolefd <= 0) + /* safety check */ + return; + else if (ioctl(gpm_consolefd, TIOCGWINSZ, &win) == -1) { return; } /*if*/ if (!win.ws_col || !win.ws_row) { @@ -197,6 +205,7 @@ int Gpm_Open(Gpm_Connect *conn, int flag Gpm_Stst *new = NULL; char* sock_name = 0; static char *consolename = NULL; + static int checked_con = 0; int gpm_is_disabled = 0; /*....................................... First of all, check xterm */ @@ -210,13 +219,17 @@ int Gpm_Open(Gpm_Connect *conn, int flag } /*....................................... No xterm, go on */ + /* consolename can be determined later + * (for example in vim gpm support it is not determined correctly + * during first Gpm_Open() call for some reason). + */ + if (! consolename) + checked_con = 0; + /* check whether we know what name the console is: what's with the lib??? */ - if(!consolename) { + if(checked_con == 0) { consolename = Gpm_get_console(); - if(!consolename) { - gpm_report(GPM_PR_ERR,"unable to open gpm console, check your /dev filesystem!\n"); - goto err; - } + checked_con++; } /* @@ -255,24 +268,79 @@ int Gpm_Open(Gpm_Connect *conn, int flag if (tty == NULL) { gpm_report(GPM_PR_ERR,"checking tty name failed"); goto err; - } - - conn->vc=atoi(&tty[strlen(consolename)-1]); + } + + /* do we really need this check ? */ + if(!consolename || strncmp(tty,consolename,strlen(consolename)-1) + || !isdigit(tty[strlen(consolename)-1])) { + + int parse, n, vc; + char* sty = getenv("STY"); + /* as set by SCREEN, e.g + * STY=417.tty1.kristine + * ^hostname + */ + + if (sty) + { + /* STY is set. Check, if it has a valid form */ + + char * host = malloc (strlen (sty)); + parse = sscanf(sty, "%d.tty%d.%s", &n, &vc, host); + + free (host); /* anybody need it ? */ + + } + + if (! sty || parse != 3) + { + gpm_report(GPM_PR_ERR,"strncmp/isdigit/consolename failed"); + if (term && strncmp (term, "screen.", 7) == 0) + gpm_report(GPM_PR_ERR,"it seems that Screen didn't set STY correctly"); + + goto err; + } + + /* we're inside a SCREEN session. Don't connect to + * the tty as below. */ + + gpm_consolefd = GPM_FD_SCREEN; + + conn->vc = vc; + win.ws_col = 80; + win.ws_row = 25; + + tty = getenv ("TTY"); + + if (tty != 0) { + + /* we can use TTY variable if it was set and exported by the shell + * for example, one can add < export TTY=`tty` > to .bashrc + * or add < export TTY > to .zshrc (zsh sets it but doesn't export). + */ + gpm_consolefd = open (tty, O_RDWR); + } + + } else { + conn->vc=atoi(&tty[strlen(consolename)-1]); + } + } else /* a default handler -- use console */ - tty=strdup(consolename); + tty=strdup(consolename); + } - if (gpm_consolefd == -1) + if (gpm_consolefd == GPM_FD_INVALID) 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 */ - ioctl(gpm_consolefd, TIOCGWINSZ, &win); + if (gpm_consolefd != GPM_FD_SCREEN) + ioctl(gpm_consolefd, TIOCGWINSZ, &win); if (!win.ws_col || !win.ws_row) { fprintf(stderr, "libgpm: zero screen dimension, assuming 80x25.\n"); @@ -376,8 +444,8 @@ int Gpm_Open(Gpm_Connect *conn, int flag /*....................................... Error: free all memory */ err: - if (gpm_is_disabled < 2) /* be quiet if no gpmctl socket found */ - gpm_report(GPM_PR_ERR,"Oh, oh, it's an error! possibly I die! "); + gpm_report(GPM_PR_ERR,"Oh, oh, it's an error! possibly I die! "); + while(gpm_stack) { new=gpm_stack->next; free(gpm_stack); @@ -422,7 +490,7 @@ int Gpm_Close(void) sigaction(SIGWINCH, &gpm_saved_winch_hook, 0); #endif close(gpm_consolefd); - gpm_consolefd=-1; + gpm_consolefd=GPM_FD_INVALID; return 0; }