mort@ihuxn.UUCP (Dubman) (12/22/83)
I am writing a program in C that requires a menu with four choices, I, D, L, and Q for Insert, Delete, List and Quit. I want to have it so that the program can key an ASCII value for the key from the VT100 terminal without having to have the user type RETURN. I tried using getchar() but inputs an entire line up to the RETURN, returns the first letter, and shoves the rest in a buffer that is emptied the next time getchar() is called. I just read that CP/M's version of C returns the value of the key as soon as the key is typed, but UNIX C (which I am using) waits for a newline. Yet, I know that many C utilities do accept a key as soon as I type it. Any ideas? Thanks in Advance, -- Jonathan Dubman - care of: Mort Dubman AT&T Bell Laboratories ihnp4!ihuxn!mort Naperville, IL.
keesan@bbncca.ARPA (Morris Keesan) (12/23/83)
---------------------------- > I want to have it so that the program can key an ASCII value for the key > from the VT100 terminal without having to have the user type RETURN. > > I tried using getchar() but inputs an entire line up to the RETURN, returns > the first letter, and shoves the rest in a buffer that is emptied the next > time getchar() is called. > > I just read that CP/M's version of C returns the value of the key as soon > as the key is typed, but UNIX C (which I am using) waits for a newline. > Yet, I know that many C utilities do accept a key as soon as I type it. -------------------------------------------------------- This is very simple, and it's nothing to do with C, but rather a UNIX(tm) feature. In normal modes, the UNIX terminal driver will do just this, hold the input until a newline is input, and then make it available to the program. What you want to do is set CBREAK mode, which will make each character available as it's typed. Try setting in from the command line by typing stty cbreak to see if it behaves the way you want it to, and then put it into your program using gtty() and stty(), or ioctl(). See ioctl(2) and tty(4). You should get the mode settings first, remember them, then set CBREAK, and restore the original modes when you're through. Note that CBREAK will effectively disable any line editing (such as erase and line-kill). -- Morris M. Keesan {decvax,linus,wjh12}!bbncca!keesan keesan @ BBN-UNIX.ARPA
ka@hou3c.UUCP (Kenneth Almquist) (12/25/83)
CBREAK mode is specific to BSD. On System III/V you can get the same effect by turning off ICANON. On Version 6 and Version 7 you can turn on RAW mode, but beware that raw mode turns off almost all driver processing. See your manual for details. Kenneth Almquist
rf@wu1.UUCP (12/28/83)
The following will work only if you controlling terminal is not
initially in cbreak mode:
system("stty cbreak");
c=getchar();
system("stty -cbreak");
Raw mode should be avoided, since it will sometimes return
characters with whose values are either less than zero or
greater than 127. A switch to raw mode may also cause the
terminal to lose some output, since raw mode disables the
XON/XOFF protocol.
You probably want to enable cbreak mode when you begin your
program and end it when you're done. The following less
portable code is a hacked version of something which does work
and is much faseter than system("stty . . .");. It probably
works, but has not been tested.
struct sgttyb otsgb;
/* iniline -- initialize line
This routine stores the terminal characteristics of stdin in
otsgb and turns on cbreak mode. If stdin's file is not a
terminal (perhaps for testing,) iniline does nothing.
*/
iniline() {
struct sgttyb ntsgb;
if (isatty(fileno(stdin))) {
ioctl(fileno(stdin), TIOCGETP, &otsgb);
ntsgb = otsgb;
ntsgb.sg_flags |= CBREAK;
ioctl(fileno(stdin), TIOCSETP, &ntsgb);
}
}
/* resetline -- reset line characteristics
This routine restores the terminal characteristics of stdin,
which should be preserved in otsgb. If the line's file is not a
terminal (perhaps for testing,) resetline does nothing.
*/
resetline() {
if (isatty(fileno(stdin))) {
ioctl(fileno(stdin), TIOCSETP, &otsgb);
}
}
Randolph Fritz
Western Union Telegraphdave@utcsrgv.UUCP (Dave Sherman) (12/29/83)
Kenneth Almquist is incorrect about CBREAK. It appears in the
v7 manual and is standard on v7. It did not exist in v6, which
had only RAW.
Dave Sherman
--
{allegra,cornell,decvax,ihnp4,linus,utzoo}!utcsrgv!daveguy@rlgvax.UUCP (Guy Harris) (12/31/83)
CBREAK mode is specific to BSD...On Version 6 and Version 7
you can turn on RAW mode, but beware that raw mode turns off
almost all driver processing.
CBREAK mode is specific to Version 7 and its descendants (at least its
descendants along the V7-2.xBSD and the V7-32V-3.xBSD-4.xBSD line); it
is not just present in BSD systems.
Guy Harris
{seismo,ihnp4,allegra}!rlgvax!guyguy@rlgvax.UUCP (Guy Harris) (12/31/83)
Two small addenda to Mr. Fritz's suggestion:
1) Doing the IOCTL's yourself will not just be faster than using
system("stty cbreak"), it will be *massively* faster if "cbreak" mode is
turned on or off more than once per session.
2) The user should ensure that "resetline" is called whenever the program
exits, even if the program is being terminated because the user hit their
interrupt key. The program should catch the SIGINT signal, and the
routine which catches this signal should restore the terminal modes and then
exit.
Guy Harris
{seismo,ihnp4,allegra}!rlgvax!guy