How can I use getch() and kbhit() from conio.h? I know that conio.h is
DOS specific, but which ones are used in Linux for that purpose? I read
that ncurses package has it....is it true? Where can I get it? How do
I use it?
Thank you,
Nitrogen,
cold...@uol.com.br
=+--+==+--+==+--+==+--+==+--+=+--+=
+ I'll see you on the other side. +
=+--+==+--+==+--+==+--+==+--+=+--+=
Sent via Deja.com
http://www.deja.com/
> How can I use getch() and kbhit() from conio.h? I know that conio.h is
> DOS specific, but which ones are used in Linux for that purpose?
curses is usually used in UNIX/Linux where conio would be under DOS.
> I read
> that ncurses package has it....is it true? Where can I get it? How do
> I use it?
It is almost certainly a part of your standard installation.
man curses
man ncurses
--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ War is a continuation of policy by other means.
\__/ Karl von Clausewitz
Official Buh rules / http://www.alcyone.com/max/projects/cards/buh/
The official rules to the betting card game, Buh.
>List,
>How can I use getch() and kbhit() from conio.h? I know that conio.h is
>DOS specific, but which ones are used in Linux for that purpose? I read
>that ncurses package has it....is it true? Where can I get it? How do
>I use it?
Curses is a pretty big package to use just to find out if someone has
pressed a key.
Think about using the *select*(2) system call instead. That system
call is a bit tricky to use, but it comes much closer to the DOS
kbhit than does curses.
(I wonder if one could implement kbhit using *select*? It probably
would not be too hard, but I think it would have to be surrounded
with a lot of caveats for general use.
--
J.Otto Tennant jo...@pobox.com
Forsan et haec olim meminisse juvabit.
Charter Member of the Vast Right Wing Conspiracy
Curses is wonderful, but it is indeed a bit much for many
situations. Below is an example of how to code getch() and
kbhit() functionality for POSIX.
/*
* kbhit(), a keyboard lookahead monitor
* getch(), a blocking single character input from stdin
*
* Plus a demo main() to illustrate usage.
*/
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
int getch(void);
int kbhit(void);
#define CMIN 1
#ifdef CTIME
#undef CTIME
#endif
#define CTIME 1
/*
* kbhit() -- a keyboard lookahead monitor
*
* returns the number of characters available to read.
*/
int
kbhit(void)
{
int cnt = 0;
int error;
static struct termios Otty, Ntty;
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
Ntty.c_oflag = 0; /* output mode */
Ntty.c_lflag &= ~ICANON; /* raw mode */
Ntty.c_cc[VMIN] = CMIN; /* minimum time to wait */
Ntty.c_cc[VTIME] = CTIME; /* minimum characters to wait for */
if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
struct timeval tv;
error += ioctl(0, FIONREAD, &cnt);
error += tcsetattr(0, TCSANOW, &Otty);
/* throw in a miniscule time delay */
tv.tv_sec = 0;
tv.tv_usec = 100;
select(1, NULL, NULL, NULL, &tv);
}
return (error == 0 ? cnt : -1 );
}
/*
* getch() -- a blocking single character input from stdin
*
* Returns a character, or -1 if an input error occurs.
*
*
* Conditionals allow compiling with or without echoing of
* the input characters, and with or without flushing pre-existing
* existing buffered input before blocking.
*
*/
int
getch(void)
{
char ch;
int error;
static struct termios Otty, Ntty;
fflush(stdout);
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
Ntty.c_oflag = 0; /* output mode */
Ntty.c_lflag &= ~ICANON; /* line settings */
#if 1
/* disable echoing the char as it is typed */
Ntty.c_lflag &= ~ECHO; /* disable echo */
#else
/* enable echoing the char as it is typed */
Ntty.c_lflag |= ECHO; /* enable echo */
#endif
Ntty.c_cc[VMIN] = CMIN; /* minimum time to wait */
Ntty.c_cc[VTIME] = CTIME; /* minimum chars to wait for */
#if 1
/*
* use this to flush the input buffer before blocking for new input
*/
#define FLAG TCSAFLUSH
#else
/*
* use this to return a char from the current input buffer, or block if
* no input is waiting.
*/
#define FLAG TCSANOW
#endif
if (0 == (error = tcsetattr(0, FLAG, &Ntty))) {
error = read(0, &ch, 1 ); /* get char from stdin */
error += tcsetattr(0, FLAG, &Otty); /* restore old settings */
}
return (error == 1 ? (int) ch : -1 );
}
/*
* a cutsie main() to demo how getch() and kbhit() work.
*/
#include <ctype.h>
int
main(void)
{
int ch, cnt;
static struct termios Otty, Ntty;
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_lflag &= ~ECHO;
printf("You must enter 10 characters to get\nthis program to continue: ");
fflush(stdout);
/* collect 10 characters */
while (1) {
if (10 <= (cnt = kbhit())) {
break;
}
}
tcsetattr(0, TCSANOW, &Ntty); /* disable echoing of further input */
printf("\nSTOP!");
fflush(stdout);
printf("\nNow type <Enter> to continue!");
fflush(stdout);
ch = getchar();
tcsetattr(0, TCSANOW, &Otty); /* enable echoing of further input */
printf("\n\nThe first five characters are: \"");
/*
* print a few chars, note that calling getch() will flush
* remaining buffered input.
*/
cnt = 4;
do {
printf("%c", ch);
ch = getchar();
} while (--cnt);
printf("%c\"\n\n", ch);
printf("\n\n *** Demo Menu ***\n\n");
printf(" Option Action\n");
printf(" A Exit and print an A word\n");
printf(" B Exit and print a B word\n");
printf(" C Exit and print a C word\n");
printf("\n Enter your choice: ?\b");
fflush(stdout);
while(1) {
switch (ch = getch()) {
case 'a': case 'A':
printf("%c\n\nThat is an *awesome* function!\n", toupper(ch));
break;
case 'b': case 'B':
printf("%c\n\nThat is a *beneficial* function!\n", toupper(ch));
break;
case 'c': case 'C':
printf("%c\n\nThat is a *critical* function!\n", toupper(ch));
break;
default:
continue;
}
break;
}
return 0;
}
--
Floyd L. Davidson <http://www.ptialaska.net/~floyd>
Ukpeagvik (Barrow, Alaska) fl...@barrow.com
> Curses is a pretty big package to use just to find out if
> someone has pressed a key.
>
> Think about using the *select*(2) system call instead. That
> system call is a bit tricky to use, but it comes much closer
> to the DOS kbhit than does curses.
> (I wonder if one could implement kbhit using *select*? It probably
> would not be too hard, but I think it would have to be surrounded
> with a lot of caveats for general use.
It is pretty simple. Change terminal io characteristics
to
ntermios.c_cc[VMIN] = 0;
ntermios.c_cc[VTIME] = 0;
tcsetattr(0, TCSADRAIN, &ntermios);
Then read a char from stdin. If it is EOF, the a key has not
been entered. Call select to wait for stdin
Something like this
int stdinready ()
{
fd_set set;
/* Initialize the file descriptor set. */
FD_ZERO (&set);
FD_SET (STDIN_FILENO, &set);
/* `select' returns 0 if timeout, 1 if input available, -1 if error. */
return (select(2,&set, NULL, NULL,NULL));
}
ttgetc()
{
int c;
c = fgetc(stdin);
if ( c == EOF){
stdinready();
c = fgetc(stdin);
}
return(255 & c); /* 8BIT */
}
I'll leave it as an exercise to figure out required headers
and so libs.
--
Dave Blake
dbl...@phy.ucsf.edu
Better add: clearerr(stdin);
| Those are really useful functions. Thanks a lot!
Why do people insist on calling it "kbhit"?
Hitting a keyboard can cause damage.
--
-----------------------------------------------------------------
| Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
| phil-...@ipal.net | Texas, USA | http://phil.ipal.org/ |
-----------------------------------------------------------------
Some hits cause damage, some don't. You can hit a cache. Hit a web
server. Hit the bottle. Hit the big time. Hit the road, Jack!
: | Those are really useful functions. Thanks a lot!
: Why do people insist on calling it "kbhit"?
: Hitting a keyboard can cause damage.
using conio.h under DOS also can cause damage. Especially to programmer's
brains.
One need to learn that he either should write programs which are pure
command-line driven and do not prevent user from redirecing input,
or write full featured screen-interface using cursess, Turbo Vision,
cxl, slang or whatever.
conio.h is too low-level for second task and causes too much
interference with first.
--
The state of some commercial Un*x is more unsecure than any Linux box
without a root password...
-- Bernd Eckenfels
The manpage for cfmakeraw -- which probably isn't POSIX -- also
suggests the following:
ntermios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
ntermios.c_oflag &= ~OPOST;
ntermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
ntermios.c_cflag &= ~(CSIZE|PARENB);
ntermios.c_cflag |= CS8;
With these modifications, a test program works, although for some
reason stdout is not translating newlines -- probably not surprising
in light of c_lflag in the above. :-)
>
>
>Then read a char from stdin. If it is EOF, the a key has not
>been entered. Call select to wait for stdin
>
>Something like this
>
> int stdinready ()
> {
> fd_set set;
> /* Initialize the file descriptor set. */
> FD_ZERO (&set);
> FD_SET (STDIN_FILENO, &set);
> /* `select' returns 0 if timeout, 1 if input available, -1 if error. */
> return (select(2,&set, NULL, NULL,NULL));
> }
>
>ttgetc()
>{
> int c;
> c = fgetc(stdin);
> if ( c == EOF){
> stdinready();
> c = fgetc(stdin);
> }
> return(255 & c); /* 8BIT */
>}
>
>
>I'll leave it as an exercise to figure out required headers
>and so libs.
No libraries are required.
These headers work:
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
although whether they're minimal or not, I can't say right now.
>
>--
>Dave Blake
>dbl...@phy.ucsf.edu
--
ew...@aimnet.com -- insert random misquote here
up 97 days, 1:35, running Linux.