Re: function to detect keyboard hit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sean,

> Is there a function in gcc to detect a keyboard hit?  Windows provides a
> function _kbhit().  It operates in non-blocking mode, returns 0 until
> the user hits a key on the keyboard.  Does gcc have the similar function
> to call?

That's not a GCC question, it's an OS question.  This is not the right forum
for your question.

Anyway...

Does the OS you are using provide a kbhit routine?

Unix-like OS APIs do not provide that kind of routine.  You can spoof one
up, though (see below).

X11 OS APIs provide something along those lines.

OS X Carbon APIs provide events, which can be used along those lines.

Amiga OS has a magic memory location that can be checked to see if the
keyboard has been hit.

So the question varies, depending on your OS, and what environment (command
line?  Carbon?  X11?  Amiga?  Apple II?  Win32?  Commodore 64?) and which OS
you are using.

For example, <http://www.flipcode.org/cgi-bin/fcarticles.cgi?show=64166>,
which would be for a Unix (POSIX) command line application.  NOTE:  I'd used
ncurses 5.5 for something like this, instead of rolling my own.
ncurses: <http://dickey.his.com/ncurses/announce.html>

Let's say you wanted to use Morgan's routine, but it's C++, and you want C.
I've made it a tiny bit more robust than Morgan's routine by taking out some
hard-coded magic values and put in the kbinit and kbfini routines, and did
it as C instead of C++.  (I've written something similar about 6 years ago,
but it was easier to Google for it than dig out my old SunOS code.)

----------------- kbhit.h -----------------
#ifdef __cplusplus
extern "C" {
#endif
int kbhit();
void kbinit();
void kbfini();
#ifdef __cplusplus
}
#endif

----------------- kbhit.c -----------------
/**
 * Unix C implementation of kbhit(), based on
 * Morgan McGuire, morgan@xxxxxxxxxxxx
 * <http://www.flipcode.org/cgi-bin/fcarticles.cgi?show=64166>
 *
 * gcc -c kbhit.c -o kbhit.o
 */

/* --- self-identity --- */
#include "kbhit.h"

/* fileno setbuf stdin */
#include <stdio.h>

/* NULL */
#include <stddef.h>

/* termios tcsetattr tcgetattr TCSANOW */
#include <termios.h>

/* ioctl FIONREAD ICANON ECHO */
#include <sys/ioctl.h>

static int initialized = 0;
static struct termios original_tty;


int kbhit() 
{
  if(!initialized)
  {
    kbinit();
  }

  int bytesWaiting;
  ioctl(fileno(stdin), FIONREAD, &bytesWaiting);
  return bytesWaiting;
}

/* Call this just when main() does its initialization. */
/* Note: kbhit will call this if it hasn't been done yet. */
void kbinit()
{
  struct termios tty;
  tcgetattr(fileno(stdin), &original_tty);
  tty = original_tty;

  /* Disable ICANON line buffering, and ECHO. */
  tty.c_lflag &= ~ICANON;
  tty.c_lflag &= ~ECHO;
  tcsetattr(fileno(stdin), TCSANOW, &tty);

  /* Decouple the FILE*'s internal buffer. */
  /* Rely on the OS buffer, probably 8192 bytes. */
  setbuf(stdin, NULL);
  initialized = 1;
}

/* Call this just before main() quits, to restore TTY settings! */
void kbfini()
{
  if(initialized)
  {
    tcsetattr(fileno(stdin), TCSANOW, &original_tty);
    initialized = 0;
  }
}

----------------------------------

To use kbhit:

----------------- demo_kbhit.c -----------------
/* gcc demo_kbhit.c kbhit.c -o demo_kbhit */
#include "kbhit.h"
#include <unistd.h>
#include <stdio.h>

int main()
{
  int c;
  printf("Press 'x' to quit\n");
  fflush(stdin);
  do
  {
    if(kbhit())
    {
      c = fgetc(stdin);
      printf("Bang: %c!\n", c);
      fflush(stdin);
    }
    else usleep(1000); /* Sleep for a millisecond. */
  } while(c != 'x');
}

----------------------------------

Hope that helps,
--Eljay

PS:  Morgan approved of my modifications, and thought I should share.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux