Subject: Re: keyboard scanning
To: None <port-arm32@NetBSD.ORG>
From: Peter Burwood <riscbsd@arcangel.dircon.co.uk>
List: port-arm32
Date: 08/25/1997 15:38:07
In message <199708232124.XAA02117@Kyra.FutureGroove.de>
          Peter Berg <root@Kyra.FutureGroove.de> wrote:

> how can I test whether a key was pressed or not without such wainting
> functions like getc() ?

Use the termios functions to change the file descriptor to RAW mode and
set the timeout and minimum characters to 0. Restore the descriptor to
the old mode afterwards. I've attached some code below (untested, but it
should work). Not many comments, but it should be obvious. If not, look
at the man pages ;-)

regards,
Pete

void
getc_nowait (FILE *stream, int *ch, int *end_of_file, int *avail)
{
  char c;
  int nread;
  int fd = fileno (stream);
  struct termios otermios_rec, termios_rec;
#if defined (linux)
  int flags;
#endif

  if (isatty (fd))
    {
      tcgetattr (fd, &termios_rec);
      memcpy (&otermios_rec, &termios_rec, sizeof (struct termios));

      /* Set RAW mode */
      termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON;
      /* Set zero wait period */
      termios_rec.c_cc[VMIN] = 0;
      termios_rec.c_cc[VTIME] = 0;
      tcsetattr (fd, TCSANOW, &termios_rec);

#if defined (linux)
      /* If we don't set this mode on Linux, Ctrl-C and Ctrl-Z processing
         get messed up */
      flags = fcntl (fd, F_GETFL);
      fcntl (fd, F_SETFL, O_NONBLOCK | flags);
#endif

      nread = read (fd, &c, 1);
      if (nread > 0)
        {
          if (c == termios_rec.c_cc[VEOF])
            {
              *avail = 0;
              *end_of_file = 1;
            }
          else
            {
              *avail = 1;
              *end_of_file = 0;
            }
        }
      else
        {
          *avail = 0;
          *end_of_file = 0;
        }

#if defined(linux)
      fcntl (fd, F_SETFL, flags);
#endif
      tcsetattr (fd, TCSANOW, &otermios_rec);
      *ch = c;
    }
  else
    /* If we're not on a terminal, then we don't need any fancy processing */
    {
      *ch = fgetc (stream);
      if (feof (stream))
        {
          *end_of_file = 1;
          *avail = 0;
        }
      else
        {
          *end_of_file = 0;
          *avail = 1;
        }
    }
}