How to write keypressed()?

Leo de Wit leo at philmds.UUCP
Mon Oct 3 05:11:34 AEST 1988


In article <315 at telesoft.UUCP> jjh at telesoft.UUCP (Jim Hayes @dance) writes:
    [introduction omitted]...
|/*===========================================================================*/
|short keypressed() {
|/* Returns 1 if a character is available for reading from stdin; 0 otherwise */
|
|  char a_char;
|  int  old_flags;
|  int  result;
|  int  retry;
|
|  if ( isatty( fileno(stdin) ) == 1 ) {
|    old_flags = fcntl(fileno(stdin), F_GETFL, 0);
|    if (old_flags < 0) {
|      return (0);
|    }
|    if ( fcntl(fileno(stdin), F_SETFL, old_flags | FNDELAY) < 0 ) {
|      return (0);
|    }
|    for (retry = 1; retry <= 10; ++retry) {
|      usleep(2000);
|      result = read(fileno(stdin), &a_char, 1);
|      if (result >= 0) {
|        ungetc(a_char, stdin);
         ^^^^^^^^^^^^^^^^^^^^^^

There's your problem: you can't ungetc a character you never read (inspecting
the return value of ungetc would indicate an error). Although you read the
character, you didn't do it using stdio, so ungetc will rightly fail.
The use of both buffered and 'raw' I/O on the same file descriptor
should be discouraged (unless you're very sure about what you're doing)
since stdio has generally spoken no means to keep track of your
reads/writes etc.

Suggestion for keypressed() (this one returns the number of characters
actually available, but you're free to use it as you like of course):


/* Returns # of characters available for reading from stdin, or a (negative)
 * error indication
 */
int keypressed()
{
    int nchars, retval;

    retval = ioctl(fileno(stdin),FIONREAD,&nchars);

    return (retval < 0) ? retval : nchars;
}

This one doesn't have your retry enhancements, but I'm sure you can merge
that in.

If you want to do asynchronous I/O (I don't know if this applies to your
application), you can also consider doing something like:

    fcntl(fileno(stdin),F_SETFL,FASYNC); /* perhaps also F_SETOWN ? */

and trapping the SIGIO signal, perhaps

    if (signal(SIGIO,SIG_IGN) != SIG_IGN) {
        signal(SIGIO,your_handler);
    }

Hope this helps -
                   Leo.



More information about the Comp.unix.wizards mailing list