[svlug] Extended Keyboard Input Utility For Bash?

Mark S Bilk mark at cosmicpenguin.com
Mon Mar 26 13:36:45 PDT 2007


On Sun, Mar 25, 2007 at 02:47:37PM -0700, Tim Utschig wrote:
>On Sat, Mar 24, 2007 at 05:21:04PM -0700, Mark S Bilk wrote:
>> On Fri, Mar 23, 2007 at 08:13:19PM -0700, Tim Utschig wrote:
>...
>If you're OK with only the current line being destroyed, this should
>work:

[C program snipped; see previous post for it.]

Thanks, Tim!

In SuSE 9.3 it needs -lncurses for compiling.  When I run it, 
it blanks the entire konsole or xterm window until I type the key,
so I lose the context of whatever's been output to the screen 
while deciding what to type.  Does this not happen on your system?

I tried putting a select() call in the code before yours, to wait
until the key is pressed, which stopped the blanking, but then it 
only gets the first byte of keypad escape sequences and only outputs 
"^[".  However, function keys are detected properly, so they must be 
getting treated differently.  Also it detects the PgUp and PgDn keys 
correctly, which are the only keypad keys that infocmp gives the 
right escape codes for.  There's something mysterious going on here 
with the keypad up, down, left, right, home, and end keys; maybe an 
extra level of translation somewhere that curses uses?  Your code
detects those keys, but putting select() before it prevents that.

Also, with the select call I have to press Enter to get it to accept 
whatever I type.  So I inserted code to set the terminal to raw mode 
before the select (see below), which eliminates the need to press 
Enter, but it's still only putting out ^[ for keypad keys (except 
PgUp and PgDn).  Commenting out the dup and dup2 calls (which I don't 
understand) and calling it directly from the command line doesn't help.

  Mark

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <curses.h>

#define STDIN_FD 0

int setraw(int fd);
int unsetraw(int fd);

int main() 
{
    int     c, orig_out;
    char   *name;
    WINDOW *wp;
	fd_set rfds;

	setraw(STDIN_FD);

	/* Watch stdin (fd 0) to see when it has input. */
	FD_ZERO(&rfds);
	FD_SET(0, &rfds);
	select(1, &rfds, NULL, NULL, NULL);
	FD_ISSET(0, &rfds);  /* select_tut(2) says this must be done */

    /* save old stdout and make stdout a dup of stderr so that curses */
    /* will work correctly when this program is called from a script  */
    /* like KEY=`getkey`                                              */
    orig_out = dup(1);
    dup2(2, 1);

    /* use a single line, leave the rest of the screen alone */
    filter();

    wp = initscr();
    noecho();
    nonl();
    cbreak();

    /* allow getch to capture multi-byte function key sequences */
    keypad(wp, TRUE);

    c = getch();
    endwin();

    dup2(orig_out, 1); /* restore original stdout */
    name = (char*)keyname(c);

	unsetraw(STDIN_FD);
    printf("%s\n", name != NULL ? name : "ERROR");

    return (name != NULL ? 0 : 1);
}

#include <asm/ioctls.h>
#include <termios.h>
	struct termios oldtty, newtty;

#define GETPARAMS TCGETS
#define SETPARAMS TCSETSW

int setraw(int fd)
{
	if ( (ioctl(fd, GETPARAMS, &oldtty)) || (ioctl(fd, GETPARAMS, &newtty)) )
  		return(-1);

	cfmakeraw(&newtty);

	return(ioctl(fd, SETPARAMS, &newtty));
}

int unsetraw(int fd)
{
	return(ioctl(fd, SETPARAMS, &oldtty));
}





More information about the Svlug mailing list