/* oskey.c - get raw keyboard input with ready testing Copyright 1990 Business Management Systems, Inc. Author: Stuart D. Gathman int Kgetc() keyboard byte stream int Kget() event (keycode) stream int Kready() event ready Function call interface loosely based on "Advanced C Programming for Displays" by Marc J. Rochkind. Events are defined in keycodes.h. Events numbered 0 - 255 are extended ascii codes. Most others are terminal function keys. Exceptions: KEY_SIG a unix signal was received KEY_SYNC there are no pending keystrokes, this might be a good time to update the display KEY_MSG a SysV message is ready, this doesn't work in SysV ?!?!?? It is possible to get keycode events from multiple terminal devices. I didn't think this was needed any time soon, so it will require an additional interface. This module is OS dependent. The keycode recognizer (Kget) is not and is in inkey.c. The MSDOS version of oskey has inkey built in since the keycode mapping is hardwired. (Do *you* know anyone that uses a serial terminal with MSDOS?) The SysV version uses stdio. It is almost certainly already linked in and does just what we want. Callers can call getchar() themselves with appropriate results. If Kready() was last called, however, getchar() will never wait. Notice also the waitkey hook on our Kgetc(). */ #include #include #include "keyboard.h" static FILE *curf = 0; void Kbegin(cnt) { static char buf[64]; curf = stdin; noecho(); nonl(); cmode(cnt); /* should be 64 if ambiguous sequences */ setvbuf(curf,buf,_IOFBF,sizeof buf); initkey(); } void Kend() { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } void Kfile(f) FILE *f; { curf = f; } /* We really aren't supposed to look at _cnt, but I'm just trying to avoid unneccsary calls to fcntl(), OK? */ static int inKgetc = 0; int Kready() { int rc; if (favail(curf) > 0) return 1; /* stuff already buffered */ if (feof(curf)) clearerr(curf); /* NDELAY already on */ else /* turn on NDELAY */ fcntl(fileno(curf),F_SETFL,O_NDELAY); rc = ungetc(getc(curf),curf); if (inKgetc) { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } return rc != EOF; } /* This is the only other "magic" that is not vanilla SysV. Waitkey is a hook available for programmers to arrange for routines to be called whenever we need to read more keyboard input. This implementation depends on a particular (but almost universal) implementation of getchar(). */ #ifdef _AIX extern int _filbuf(FILE *); int (*waitkey)(FILE *) = _filbuf; #elif __linux__ static int _filbuf(FILE *f) { int rc = __underflow(f); if (rc < 0) return rc; return getc(curf); } int (*waitkey)(FILE *) = _filbuf; #else #error Need stdio underflow hook #endif int Kgetc() { int rc; if (feof(curf)) { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } inKgetc = 1; if (!Kready()) rc = (*waitkey)(curf); else rc = getc(curf); inKgetc = 0; return rc; }