Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Checking for a keypress on Linux ?????

1,407 views
Skip to first unread message

Koen

unread,
Sep 11, 2003, 8:03:59 AM9/11/03
to
Hi,

could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard. I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit() from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!

Koen


Lew Pitcher

unread,
Sep 11, 2003, 9:07:23 AM9/11/03
to
On Thu, 11 Sep 2003 14:03:59 +0200, "Koen" <n...@ssppaamm.com> wrote:

>Hi,
>
>could anyone please tell me how one can check (using C or C++ code)
>whether a key was pressed on the keyboard? This is for use with
>console based applications that don't have fancy UI, but do need
>polling for (or callback on) a keypress on the keyboard.

Typically, if your application is designed to require knowledge of "keypress",
then the application is not designed correctly for Linux.

However, "keypress" knowledge is available through the use of tty-device ioctl()
calls and/or the use of the ncurses API.

> I'm not
>talking about getting a character from the input queue, since that
>won't work until you press enter...
>In the Windows world, this is *very* simple using kbhit()

Two points:
1) Windows was not designed to be a multi-user operating system, and
consequently provides 'features' that can only be used properly on
a single-user OS.
2) Stop thinking about developing Linux programs in the Windows model.
Start thinking about developing Linux programs in the Unix model.
I realize that you'll have to relearn a number of things, but if
you /don't/ learn how to develop under the Unix model, your programs
will be overly complex, easily breakable, and will ultimately either
break the Unix standards or be so convoluted as to be unmaintainable.


> from
>conio.h, but I didn't find anything in Linux and of course I must be
>able to do it on Linux too!
>
>Koen
>
>

--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group

(Opinions expressed are my own, not my employers')

jo...@onevista.com

unread,
Sep 11, 2003, 9:28:52 AM9/11/03
to

Here's some C code:

#include <termios.h>
#include <unistd.h>

struct termios argin, argout;
unsigned char ch = 0;

kbhit()
{
tcgetattr(0,&argin);
argout = argin;
argout.c_lflag &= ~(ICANON);
argout.c_iflag &= ~(ICRNL);
argout.c_oflag &= ~(OPOST);
argout.c_cc[VMIN] = 1;
argout.c_cc[VTIME] = 0;
tcsetattr(0,TCSADRAIN,&argout);
read(0, &ch, 1);
tcsetattr(0,TCSADRAIN,&argin);
}

Kevin Easton

unread,
Sep 11, 2003, 9:33:17 AM9/11/03
to

The equivalent to conio.h in unixy systems is the curses library - in
particular the ncurses implementation is popular on linux (this is what
programs like the bash shell use). You want getch() in no-delay mode.

- Kevin.

Koen

unread,
Sep 12, 2003, 4:25:07 AM9/12/03
to
"Lew Pitcher" <Lew.P...@td.com> wrote in message
news:3f607186...@news21.on.aibn.com...

> On Thu, 11 Sep 2003 14:03:59 +0200, "Koen" <n...@ssppaamm.com> wrote:

> Typically, if your application is designed to require knowledge of
"keypress",
> then the application is not designed correctly for Linux.

Now, listen. I'm really fed up with this kind of arrogant comments by
all-knowing Linux guys (I know there are others too, so I won't
generalize).

What you're saying is that an application that uses keypresses to let
a user play a melody on his keyboard (to give an example) is not
something that should be done on Linux. Well, I really hope you can
live with that, but it's 2003, and I can't, OK?

And by the way: this is what someone else posted as a reply to my
post:


"The equivalent to conio.h in unixy systems is the curses library - in
particular the ncurses implementation is popular on linux (this is
what
programs like the bash shell use). You want getch() in no-delay
mode."

So the bash shell is "not designed correctly for Linux" then (your
quote)?
I'm really fed up with this kind of arrogancy, sorry (even if there
might be truth in some of your remarks, I'm not a black-and-white type
of guy).

> However, "keypress" knowledge is available through the use of
tty-device ioctl()
> calls and/or the use of the ncurses API.

Right. So there was a need after all? Well, well.

> Two points:
> 1) Windows was not designed to be a multi-user operating system, and
> consequently provides 'features' that can only be used properly
on
> a single-user OS.

Now I'm not following you any longer: a few lines above you say that
it IS possible using the mentioned calls and/or ncurses API...

> 2) Stop thinking about developing Linux programs in the Windows
model.
> Start thinking about developing Linux programs in the Unix model.
> I realize that you'll have to relearn a number of things, but if
> you /don't/ learn how to develop under the Unix model, your
programs
> will be overly complex, easily breakable, and will ultimately
either
> break the Unix standards or be so convoluted as to be
unmaintainable.

OK. Granted in general, but not for the keypress issue.

Really, I can take lots of advice, and I generally like it if people
tell me things to be careful with (that's why I visit newsgroups,
apart from helping out others), but your reply is plain arrogance.
I'm glad I know some other Linux developers that seem to behave
different from you, so I won't generalize this.

Anyway, have a nice life. And thanks anyway for the pointers.

Koen


Koen

unread,
Sep 12, 2003, 4:29:32 AM9/12/03
to
<jo...@onevista.com> wrote in message
news:HL1xG...@flash.onevista.com...

> Here's some C code:
>
> #include <termios.h>
> #include <unistd.h>
>
> struct termios argin, argout;
> unsigned char ch = 0;
>
> kbhit()
> {
> tcgetattr(0,&argin);
> argout = argin;
> argout.c_lflag &= ~(ICANON);
> argout.c_iflag &= ~(ICRNL);
> argout.c_oflag &= ~(OPOST);
> argout.c_cc[VMIN] = 1;
> argout.c_cc[VTIME] = 0;
> tcsetattr(0,TCSADRAIN,&argout);
> read(0, &ch, 1);
> tcsetattr(0,TCSADRAIN,&argin);
> }

Thanks! I'll try that!
Koen


Koen

unread,
Sep 12, 2003, 4:30:12 AM9/12/03
to
"Kevin Easton" <kevin@-nospam-pcug.org.au> wrote in message
news:newscache$gnx1lh$svd$1...@tomato.pcug.org.au...

>
> The equivalent to conio.h in unixy systems is the curses library -
in
> particular the ncurses implementation is popular on linux (this is
what
> programs like the bash shell use). You want getch() in no-delay
mode.

OK. Thanks for the info, Kevin.
Koen


Ivar Nilsson

unread,
Sep 12, 2003, 5:29:22 AM9/12/03
to
On Thu, 11 Sep 2003 14:03:59 +0200, "Koen" <n...@ssppaamm.com> wrote:

Here is some code I've used from the net, auther unkown and #include
whatever it needs. It works for me so I don't think more about it...

int kbhit(void)
{
struct timeval tv; fd_set
read_fd; /* Do not wait at all, not even a microsecond */
tv.tv_sec=0;
tv.tv_usec=0; /* Must be done first to initialize read_fd */
FD_ZERO(&read_fd); /* Makes select() ask if input is ready: *
0 is the file descriptor for stdin */
FD_SET(0,&read_fd); /* The first parameter is the number of the *
largest file descriptor to check + 1. */
if(select(1, &read_fd, NULL, /*No writes*/ NULL, /*No exceptions*/
&tv) == -1)
return 0; /* An error occured */

/* read_fd now holds a bit map of files that are *
readable. We test the entry for the standard *
input (file 0). */
if(FD_ISSET(0,&read_fd)) /* Character pending on stdin */
return 1; /* no characters were pending */
return 0;
}


/Ivar

Thomas Richter

unread,
Sep 12, 2003, 6:01:36 AM9/12/03
to
Hi,

>> Typically, if your application is designed to require knowledge of
> "keypress",
>> then the application is not designed correctly for Linux.

> Now, listen. I'm really fed up with this kind of arrogant comments by
> all-knowing Linux guys (I know there are others too, so I won't
> generalize).

While I agree with you that this kind of answer is agorrant and
unsuitable, I have to agree that you need to state your problem
clearer. "Keypress" has several abstractions, and dependent on what
*exactly* you want to do, some of them might be more apropriate than
others.

> What you're saying is that an application that uses keypresses to let
> a user play a melody on his keyboard (to give an example) is not
> something that should be done on Linux.

It should be done on Linux, but it should be done in a different
way than "conio.h" and doing that from the shell. A keypress for a console
applications has other semantics than a keypress for a graphical end
user application. Your users won't be happy if they would have to hold
the shell window open and active to play a melody. They would be happy
if there would be a graphical keyboard on the screen that, when activated
by the window manager (say, KDE) plays a melody when the keys are pressed.

In this case, the X11 system (or its various helper libraries) seem to
be much more suitable to solve your problem than to go for the console.

> And by the way: this is what someone else posted as a reply to my
> post:
> "The equivalent to conio.h in unixy systems is the curses library - in
> particular the ncurses implementation is popular on linux (this is
> what
> programs like the bash shell use). You want getch() in no-delay
> mode."

> So the bash shell is "not designed correctly for Linux" then (your
> quote)?

"The bash shell is not designed correctly to play a melody." Yes, I'll
sign that. (-;

> I'm really fed up with this kind of arrogancy, sorry (even if there
> might be truth in some of your remarks, I'm not a black-and-white type
> of guy).

Me, too. (-;

But then, it's better to give backgrounds about the problem you want
to solve than to state the problem "I want a keypress". There is no
single solution that is suitable for all problems, as there is no
concept of "a keypress". There is a concept of "getting a single
character unbuffered from an input stream", which has one concrete
realisation in the console connected to the keyboard, and "get an
X11 keypress event", which is suitable for graphical applications.

> Now I'm not following you any longer: a few lines above you say that
> it IS possible using the mentioned calls and/or ncurses API...

Yes, but that's maybe not want you want/need.

> OK. Granted in general, but not for the keypress issue.

Yes, especially for this issue, I afraid. (-;

> Really, I can take lots of advice, and I generally like it if people
> tell me things to be careful with (that's why I visit newsgroups,
> apart from helping out others), but your reply is plain arrogance.

Yup, no question. /-:

So long,
Thomas

Floyd Davidson

unread,
Sep 12, 2003, 6:17:21 AM9/12/03
to

There are at least three basic, and relatively simple, ways to
write a kbhit() function for unix. However, there are many more
minor variations one might choose to implement, and there are
also some tricks that don't meet the eye immediately.

The below demo program is one that I've been posting for more
than a decade. It has undergone a number of changes, as it
originally used K&R C and termio instead of POSIX termios.

There have also been modification as a result of feedback from
people who've tried it. For example, the short delay in kbhit()
was not originally there, until some fool who didn't know you
shouldn't put it in a tight loop did. It dropped characters!
So that fool convinced the fool who knew better to make is work
in that tight loop too... ;-)

Do *not* take this as *the* definition of kbhit(), it isn't.
What it is, is just a demonstration of where you want to start,
and with a few hints about how to avoid some problems. Some of
the hints are not explicit, so when you go to change something
it would be very wise to think very hard about what the total
effect will be.

/*
* 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 count = 0;
int error;
static struct termios Otty, Ntty;

tcgetattr(STDIN_FILENO, &Otty);
Ntty = Otty;

Ntty.c_lflag &= ~ICANON; /* raw mode */
Ntty.c_cc[VMIN] = CMIN; /* minimum chars to wait for */
Ntty.c_cc[VTIME] = CTIME; /* minimum wait time */

if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) {
struct timeval tv;
error += ioctl(STDIN_FILENO, FIONREAD, &count);
error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty);
/* minimal delay gives up cpu time slice, and
* allows use in a tight loop */
tv.tv_sec = 0;
tv.tv_usec = 10;
select(1, NULL, NULL, NULL, &tv);
}

return (error == 0 ? count : -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(STDIN_FILENO, &Otty);
Ntty = Otty;

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 chars to wait for */
Ntty.c_cc[VTIME] = CTIME; /* minimum wait time */

#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(STDIN_FILENO, FLAG, &Ntty))) {
/* get a single character from stdin */
error = read(STDIN_FILENO, &ch, 1 );
/* restore old settings */
error += tcsetattr(STDIN_FILENO, FLAG, &Otty);
}

return (error == 1 ? (int) ch : -1 );
}


/*
* a cutsie main() to demo how getch() and kbhit() work.
*/

#include <ctype.h>

int
main(void)
{
int ch, count;
static struct termios Otty, Ntty;

tcgetattr(STDIN_FILENO, &Otty);
Ntty = Otty;
Ntty.c_lflag &= ~ECHO;

printf("You must enter 10 characters to get\n");
printf("this program to continue: ");
fflush(stdout);
/* collect 10 characters */
while (1) {
if (10 <= (count = kbhit())) {
break;
}
}

tcsetattr(STDIN_FILENO, TCSANOW, &Ntty); /* disable echoing */
printf("\nSTOP!");
fflush(stdout);
printf("\nNow type <Enter> to continue!");
fflush(stdout);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &Otty); /* enable echoing */
printf("\n\nThe first five characters are: \"");
/*
* print a few chars, note that calling getch() will flush
* remaining buffered input.
*/
count = 4;
do {
printf("%c", ch);
ch = getchar();
} while (--count);
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://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) fl...@barrow.com

Joe Beanfish

unread,
Sep 12, 2003, 1:52:08 PM9/12/03
to

Please don't much the cpu like that. Just call getch()
10 times to get the 10 characters. But if you insist
on doing the above you might want to do it right
while((count=kbhit())<10);

Sybren Stuvel

unread,
Sep 12, 2003, 3:16:25 PM9/12/03
to
Joe Beanfish enlightened us with:

> Please don't much the cpu like that.

Could you next time please snip your post? You're quoting about 160
lines of text, and you're making us scroll down a few pages before we
can read your post. This only gives top-posters more reason to keep on
top-posting. Quoting the entire previous post is unneeded. There are
people that have to pay per minute for their internet connection, and
I myself, I'm og ften reading this newsgroup on a handheld. The screen
is rather small, so then I really have to scroll down a lot before I
can read anything you wrote. Please snip your post.

Sybren
--
The problem with the world is stupidity. Not saying there should be a
capital punishment for stupidity, but why don't we just take the
safety labels off of everything and let the problem solve itself?

Floyd Davidson

unread,
Sep 12, 2003, 4:04:24 PM9/12/03
to
Joe Beanfish <joebe...@nospam.duh> wrote:

...

>> while (1) {
>> if (10 <= (count = kbhit())) {
>> break;
>> }
>> }
>
>Please don't much the cpu like that. Just call getch()

Please read the code first. It doesn't eat the cpu, as the
select call forces the process to give up its slice every time.

Note that explicit reference was made in the commentary
provided, and it is also commented in the code itself.

There is no advantage (actually either way) to calling getch()
or calling kbhit(). But I did feel that in a demo program the
kbhit() functionality was better to exhibit.

>10 times to get the 10 characters. But if you insist
>on doing the above you might want to do it right
> while((count=kbhit())<10);

That code is part of a demo for relative newbies. It is *not*
demonstrating how to make code unreadable, cryptic, or lacking
in white space. It's purpose is to make reading the code
transparent even for those with relatively little experience,
with the intention that they focus on what the program does
overall. Your code is *asking* for errors. It lacks necessary
white space to make it readable, and it has an unnecessary empty
loop.

Koen

unread,
Sep 12, 2003, 6:02:12 PM9/12/03
to
"Floyd Davidson" <fl...@barrow.com> wrote in message
news:87k78ex...@barrow.com...

> The below demo program is one that I've been posting for more
> than a decade. It has undergone a number of changes, as it
> originally used K&R C and termio instead of POSIX termios.
>

> <...SNIP...>


>
> Do *not* take this as *the* definition of kbhit(), it isn't.
> What it is, is just a demonstration of where you want to start,
> and with a few hints about how to avoid some problems. Some of
> the hints are not explicit, so when you go to change something
> it would be very wise to think very hard about what the total
> effect will be.

Thanks for the code Floyd!
That gives me a clue about where to go and look indeed. And the example also
shows the use in practice. I'll save this post.

Koen


Koen

unread,
Sep 12, 2003, 6:18:05 PM9/12/03
to
"Thomas Richter" <th...@cleopatra.math.tu-berlin.de> wrote in message
news:bjs5i0$kmh$2...@mamenchi.zrz.TU-Berlin.DE...

> It should be done on Linux, but it should be done in a different
> way than "conio.h" and doing that from the shell. A keypress for a console
> applications has other semantics than a keypress for a graphical end
> user application. Your users won't be happy if they would have to hold
> the shell window open and active to play a melody. They would be happy
> if there would be a graphical keyboard on the screen that, when activated
> by the window manager (say, KDE) plays a melody when the keys are pressed.
>
> In this case, the X11 system (or its various helper libraries) seem to
> be much more suitable to solve your problem than to go for the console.

Just very short:
- I don't want to play a melody on my keyboard at all, it was just an
example of showing what one COULD do with a kbhit-like function
- I never concluded from the mentioned posts that the bash shell is or is
not designed to play a melody
- it seems like there were a lot of people that did exactly get what I was
meaning
- never mind spending more time on this: I got what I wanted and you
probably have much more important things to do than following this thread
I'll try to be clearer next time.
Koen


Joe Beanfish

unread,
Sep 15, 2003, 1:49:24 PM9/15/03
to

I did read it. It's still better to just hand over to a blocking
kernel call than to have to keep returning to user space. If you
wanted to do something else while also waiting for keystrokes
that would be different matter. It might be interesting to
compare real world cpu usage of both methods though.

> >10 times to get the 10 characters. But if you insist
> >on doing the above you might want to do it right
> > while((count=kbhit())<10);
>
> That code is part of a demo for relative newbies. It is *not*
> demonstrating how to make code unreadable, cryptic, or lacking
> in white space.

Not the intent at all. Use whatever formatting you like. The
extra whitespace is actually harder for me to read. I know some
people like it in there. And

> It's purpose is to make reading the code
> transparent even for those with relatively little experience,
> with the intention that they focus on what the program does
> overall. Your code is *asking* for errors. It lacks necessary
> white space to make it readable, and it has an unnecessary empty
> loop.

You're encouraging bad practice and misdirecting newbies by not
putting the condition in the while where it belongs. Now some
newbie's going to code all loops with while(1) and a check
inside the loop. Besides, what newbie can deal with a comparison
and assignment in one statement? if (10 <= (count = kbhit()))

Take it FWIW, I don't want to start a flame war over styles etc.

Floyd Davidson

unread,
Sep 15, 2003, 5:17:08 PM9/15/03
to
Joe Beanfish <joebe...@nospam.duh> wrote:
>> There is no advantage (actually either way) to calling getch()
>> or calling kbhit(). But I did feel that in a demo program the
>> kbhit() functionality was better to exhibit.
>
>I did read it.

Apparently not. Your original comment was totally wrong.

> It's still better to just hand over to a blocking

And you *still* haven't caught on that the program is intended
to demonstrate the functionality of kbhit(). It is not
claimed to be the best use, just an _indication_ of the
way it can be applied.

>... It might be interesting to


>compare real world cpu usage of both methods though.

Try it. You'll be surprised.

>You're encouraging bad practice and misdirecting newbies by not
>putting the condition in the while where it belongs. Now some

You are suggesting that empty loops are less of a problem.

>Take it FWIW, I don't want to start a flame war over styles etc.

Sure. That's why you posted a poorly thought style flame.

Message has been deleted

Floyd Davidson

unread,
Sep 23, 2003, 12:50:10 AM9/23/03
to
sabun...@yahoo.com (Sam Abu-Nassar) wrote:
>"Koen" <n...@ssppaamm.com> wrote in message news:<bjpnbo$r5c$1...@gaudi2.UGent.be>...
>The Curses library was the easiest way I could find to implement
>kbhit() in Linux. Although I use a custom library, which gives me

The curses library (actually, ncurses) is a great package, but
invoking it just to get the functionality for kbhit() is a bit
much in my book.

Below is an example of how easily kbhit() functionality can be
coded up in about 20 lines of code with only the standard clib
functions. Along with it is an example for getch() too, plus a
short demo program illustrating usage.

/*
* 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 <time.h>
#include <sys/ioctl.h>
#include <sys/types.h>

int getch(void);
int kbhit(void);

/*


* kbhit() -- a keyboard lookahead monitor
*
* returns the number of characters available to read.
*/
int
kbhit(void)
{
int count = 0;
int error;

struct timespec tv;
struct termios otty, ntty;

tcgetattr(STDIN_FILENO, &otty);
ntty = otty;
ntty.c_lflag &= ~ICANON; /* raw mode */

if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &ntty))) {


error += ioctl(STDIN_FILENO, FIONREAD, &count);

error += tcsetattr(STDIN_FILENO, TCSANOW, &otty);


/* minimal delay gives up cpu time slice,

* allows use in a tight loop */
tv.tv_sec = 0;

tv.tv_nsec = 10;
nanosleep(&tv, NULL);
}

return error == 0 ? count : -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)
{

unsigned char ch;
int error;
struct termios otty, ntty;

fflush(stdout);
tcgetattr(STDIN_FILENO, &otty);
ntty = otty;

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] = 1; /* block for input */
ntty.c_cc[VTIME] = 0; /* timer is ignored */

#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(STDIN_FILENO, FLAG, &ntty))) {


/* get a single character from stdin */
error = read(STDIN_FILENO, &ch, 1 );
/* restore old settings */

error += tcsetattr(STDIN_FILENO, FLAG, &otty);
}

return (error == 1 ? (int) ch : -1 );
}


/*
* a cutsie main() to demo how getch() and kbhit() work.
*/

#include <ctype.h>

int
main(void)
{
int ch, count;

static struct termios otty, ntty;

printf("You must enter 10 characters to get\n");
printf("this program to continue: ");
fflush(stdout);

/* collect 10 characters */

while (1) {
if (10 <= (count = kbhit())) {
break;
}
}

/* disable echoing keyboard input */
tcgetattr(STDIN_FILENO, &otty);
ntty = otty;
ntty.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &ntty);

printf("\nSTOP!");
fflush(stdout);
printf("\nNow type <Enter> to continue!");
fflush(stdout);
ch = getchar();

/* re-enable echoing */
tcsetattr(STDIN_FILENO, TCSANOW, &otty);


printf("\n\nThe first five characters are: \"");
/*
* print a few chars, note that calling getch() will

* flush remaining buffered input.

--

PenguinsAnonymous

unread,
Sep 25, 2003, 9:14:29 PM9/25/03
to

I've read this a couple times and it's not insulting at all!
Lew says how to use ncurses to achieve it and offers a
perspective adjustment that should be thought about.

When I'm eating an orange I don't try to slice it like an apple.
But then some people do don't they.
:)
-Walt

Thanks Lew!


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----

Lew Pitcher

unread,
Sep 26, 2003, 8:05:50 AM9/26/03
to
PenguinsAnonymous wrote:
> In comp.os.linux.development Lew Pitcher <Lew.P...@td.com> wrote:
>
>>On Thu, 11 Sep 2003 14:03:59 +0200, "Koen" <n...@ssppaamm.com> wrote:
>
>
>>>Hi,
>>>
>>>could anyone please tell me how one can check (using C or C++ code)
>>>whether a key was pressed on the keyboard? This is for use with
>>>console based applications that don't have fancy UI, but do need
>>>polling for (or callback on) a keypress on the keyboard.
[snip]

>>Two points:
>>1) Windows was not designed to be a multi-user operating system, and
>> consequently provides 'features' that can only be used properly on
>> a single-user OS.
>>2) Stop thinking about developing Linux programs in the Windows model.
>> Start thinking about developing Linux programs in the Unix model.
>> I realize that you'll have to relearn a number of things, but if
>> you /don't/ learn how to develop under the Unix model, your programs
>> will be overly complex, easily breakable, and will ultimately either
>> break the Unix standards or be so convoluted as to be unmaintainable.
>
>
> I've read this a couple times and it's not insulting at all!
> Lew says how to use ncurses to achieve it and offers a
> perspective adjustment that should be thought about.
>
> When I'm eating an orange I don't try to slice it like an apple.
> But then some people do don't they.
> :)
> -Walt
>
> Thanks Lew!

You're welcome, Walt

I'm just waiting for the OP to ask how he now avoids the pitfalls of his
keypress function when his app is run in a pipeline, or by a networked user
(or, for that matter, invoked by a TK script that provides a GUI wrapper
around the original program).

--

Lew Pitcher, IT Consultant, Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)

Floyd Davidson

unread,
Sep 26, 2003, 3:39:32 PM9/26/03
to
Lew Pitcher <Lew.P...@td.com> wrote:
>PenguinsAnonymous wrote:
>> In comp.os.linux.development Lew Pitcher <Lew.P...@td.com> wrote:
>>>On Thu, 11 Sep 2003 14:03:59 +0200, "Koen" <n...@ssppaamm.com> wrote:
>>>>could anyone please tell me how one can check (using C or C++ code)
>>>>whether a key was pressed on the keyboard? This is for use with
>>>>console based applications that don't have fancy UI, but do need
>>>>polling for (or callback on) a keypress on the keyboard.

...

>>>Two points:
>>>1) Windows was not designed to be a multi-user operating system, and
>>> consequently provides 'features' that can only be used properly on
>>> a single-user OS.
>>>2) Stop thinking about developing Linux programs in the Windows model.
>>> Start thinking about developing Linux programs in the Unix model.
>>> I realize that you'll have to relearn a number of things, but if
>>> you /don't/ learn how to develop under the Unix model, your programs
>>> will be overly complex, easily breakable, and will ultimately either
>>> break the Unix standards or be so convoluted as to be unmaintainable.
>>
>>
>> I've read this a couple times and it's not insulting at all!
>> Lew says how to use ncurses to achieve it and offers a
>> perspective adjustment that should be thought about.
>>
>> When I'm eating an orange I don't try to slice it like an apple.
>> But then some people do don't they.
>> :)
>> -Walt
>>
>> Thanks Lew!
>
>You're welcome, Walt
>
>I'm just waiting for the OP to ask how he now avoids the pitfalls of his
>keypress function when his app is run in a pipeline, or by a networked user
>(or, for that matter, invoked by a TK script that provides a GUI wrapper
>around the original program).

Then again, the OP could be learning how to code a text
editor... Or a command line shell... Or a terminal/modem
program... Or any of a number of other tasks that are best done
using raw input.

And his request would then be quite reasonable, particularly in
a multiuser environment.

We might want to discuss select(2), or the FIONREAD ioctl
command, rather than make comparisons to single user OS's that
are of no real consequence.

PenguinsAnonymous

unread,
Sep 27, 2003, 10:30:05 AM9/27/03
to
Lew Pitcher <Lew.P...@td.com> wrote:

> I'm just waiting for the OP to ask how he now avoids the pitfalls of his
> keypress function when his app is run in a pipeline, or by a networked user
> (or, for that matter, invoked by a TK script that provides a GUI wrapper
> around the original program).

If part of a product the potential for support annoyance
will teach a perspective quickly :)

-Walt

0 new messages