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 Telegraph
dave@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!dave
guy@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!guy
guy@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