arnold@gatech.UUCP (06/10/83)
I am working on and off on a screen editor which I have adapted to use the (4.1) curses package. The editor makes use of control characters for doing various things, including things like DEL and Control-\ which normally send interrupts. In order to get one character at a time, I do the following: (echo is previously turned off, using the noecho() call.) raw(); c = getchar(); noraw(); c &= 0177; /* lop off parity bit */ return(c); The problem when I do this is that I lose all type ahead when the editor is redrawing the screen or searching or such. My question then is, how can I continue to do raw I/O for the control characters, but keep the type-ahead? I know it's possible, becuase VI does it. Thanks in advance Arnold Robbins (Unix Apprentice: Neophyte < Apprentice < Wizard) -- "The parchment and quill pen of Arnold Robbins" Arnold @ GATech (CS Net) Arnold.GATech @ UDel-Relay (ARPA) School of ICS ...!{sb1, allegra}!gatech!arnold (uucp) Georgia Tech ...!duke!mcnc!msdc!gatech!arnold Atlanta, GA 30332 ...!decvax!cornell!allegra!gatech!arnold
guy@rlgvax.UUCP (06/11/83)
Leave the terminal in CBREAK mode (NOT RAW mode - see previous submission)
all the time; if you want to disable the interrupt and quit characters,
set them to '\0377' using the TIOCGETC and TIOCSETC "ioctl" calls.
What you do is:
#include <whatever you are including>
#include <curses.h>
#include <sgtty.h>
main()
{
struct tchars oldtchars, newtchars;
initialization;
enter "curses";
crmode();
ioctl(_tty_ch, TIOCGETC, &oldtchars);
newtchars = oldtchars;
newtchars.t_intrc = '\0377';
newtchars.t_quitc = '\0377';
ioctl(_tty_ch, TIOCSETC, &newtchars);
do whatever your program does;
nocrmode();
ioctl(_tty_ch, TIOCSETC, &oldtchars);
leave "curses";
exit(<your exit code>);
}
The reason typeahead was flushed was that you were going into and out of RAW
mode before each read; going into or out of RAW (or CBREAK) mode flushes all
typeahead. It also consumes a lot of CPU time; furthermore, it means that
while you aren't waiting for a character your program is vulnerable to
interrupts! If you are using the job control mechanism, you may want either
to disable their control characters as well (see the manual page TTY(4)) or
catch them.
Guy Harris
RLG Corporation
{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy
guy@rlgvax.UUCP (06/11/83)
The difference between RAW and CBREAK mode, in 25 words or less: RAW mode means 8-bit data path, with no parity checking no special character interpretation whatsoever wakeup on every character is possible no special output processing whatsoever CBREAK mode means 7-bit data path, with whatever parity checking is enabled "line processing" (erase, kill, EOF, special EOL, and retype on 4.1BSD) is disabled, BUT the interrupt and quit characters are enabled (as are the other signalling characters on 4.1BSD); furthermore, XON/XOFF processing is also active wakeup on every character is possible no change to the output processing from COOKED mode whatsoever Programs which run interactively on a keystroke basis should NEVER run in RAW mode, only CBREAK mode. CBREAK mode is intended for exactly those kinds of programs; RAW mode is SOLELY intended for binary data transmission (like UUCP). For USG UNIX, read ~ICANON mode for CBREAK mode and read "some very complicated set of bits turned on and off" for RAW mode. "curses" has the "functions" (actually macros, at least in 4.1BSD) "crmode" and "nocrmode", which function analogously to "raw" and "noraw" except that they put the terminal in CBREAK mode rather than RAW mode. I've noticed several references to RAW mode being what screen editors and the like run in. This is either due to the fact that RAW mode was all you had on V6, or due to people simply not being aware of CBREAK mode, or due to people not being aware how obnoxious RAW mode is for interaction with a human at a terminal. In USG UNIX, you CAN turn on 8-bit characters without turning off the interrupt characters and XON/XOFF, but your terminal better use the 8th bit for information rather than parity. Guy Harris RLG Corporation {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy
obrien%rand-unix@sri-unix.UUCP (06/13/83)
This message is empty.
ptw@vaxine.UUCP (P. Tucker Withington) (06/13/83)
Just a nit, but CBREAK does have *one* effect on output (which could really drive you nuts). The normal tty driver will not let you *send* EOT (it silently ignores it). This is to "avoid hanging up some terminals". The bummer is, that some other "terminals" (e.g., Diablo and emulations) use small numbers for absolute motions and other terminal settings. We ran into this problem when we fine-tuned nroff to really use our Spinwriter. It would "glitch" now and again. The problem was solved by printing in CBREAK mode. --Tucker (ptw@vaxine.UUCP)
guy@rlgvax.UUCP (06/14/83)
What really rots about that is that ONLY on 4.1BSD can you output an EOT in CBREAK mode; it's not in standard V7. The USG UNIX tty driver solves this by the simple expedient of not echoing your EOF character, and passing EOT through in all modes like any other character. Now if it would only echo control characters, or at least the special TTY driver control characters, as "^<whatever>", so you could get visual feedback that the EOT actually got through to the computer... Guy Harris RLG Corporation {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy
SJOBRG.ANDY%MIT-OZ%mit-ml@sri-unix.UUCP (06/14/83)
Well, perhaps you should run in CBREAK mode, and then set all of the interrupt characters that remain to be \377 -- the tty driver will then ignore them, and you will get your buffered input. However, you will NOT get 8 bits, just the usual 7.
ellis@flairvax.UUCP (06/15/83)
While we're on this topic, does anyone out there have any idea how to switch back & forth between 7-bit & 8-bit character input modes WITHOUT flushing queued input characters ? Currently, switching to RAW mode is the only way to get all 8 bits, and doing this (even if you use TIOCSETN) causes input flushing. This is all for a program that reads from a keyboard with a META-shift key (which sets the 'parity' bit) and then executes programs expecting the normal UNIX tty environment. Currently, all type-ahead is lost. I realize that several kernel mods would be required to do what I want.. Michael Ellis - Fairchild AI Lab - Palo Alto CA - (415) 858 4270
z@cca.UUCP (06/16/83)
Shortly after 4.1BSD came out, I made some rather trivial mods to the kernel to add L8BIT, a new bit in the local mode word of the tty driver. Setting L8BIT allows you to transmit and receive all eight bits in either cooked or CBREAK mode. My inspiration was also a terminal with a META key; I wanted to use all eight bits but still have flow control. I tried convincing Berkeley to incorporate this into 4.2BSD, but they weren't interested. If there is sufficient interest, I can post these mods to the net. Steve Zimmerman
chris@umcp-cs.UUCP (06/16/83)
Now for my two cent's worth: I'd like a full set of options, like so: IN_8BIT /* 8 bit input */ OUT_8BIT /* 8 bit output */ ECHO /* echo all input */ CTLECHO /* echo control chars as ^x */ CBREAK /* wake up on all input */ the usual tab, CR, NL, FF delay/expansion ECHONL /* Echo NL after CR, for half-duplex with ~ECHO */ BREAKNULL /* Change BREAK to null instead of sending signal */ BREAKIGN /* Ignore BREAK completely */ and all the special characters in one structure. No need for a RAW mode; it's just IN_8BIT|OUT_8BIT|CBREAK|BREAKNULL, with all the special characters turned off. The reason for BREAKNULL and BREAKIGN? Well, BREAKNULL is for those programs that look for NULL, in RAW, as a change- speed code (i.e. getty). BREAKIGN is for noisy lines, where you get spurious BREAKs, which are currently nearly impossible to get around. If you set neither, then BREAK should generate SIGINT in ANY mode. - Chris -- UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris.umcp-cs@UDel-Relay
guy@rlgvax.UUCP (06/16/83)
The USG tty driver's equivalent of these bits: IN_8BIT /* 8 bit input */ Turn off ISTRIP (strip input characters to 7 bits) and INPCK (enable input parity checking) in c_iflag. OUT_8BIT /* 8 bit output */ Set the character size to CS8 (yes, it also supports CS5 and CS6 as well as CS7) and turn off PARENB in c_cflag. The ability to select 7+parity vs. 8 on input independly from on output depends, of course, on the hardware supporting it; reading the "Terminals and Communications Handbook", my interpretation is that if you set 7+parity you will still get handed all 8 bits on input, but you can tell the receiver not to check parity on input while it still generates parity on output. The ISTRIP bit doesn't condition any hardware bits, it merely controls whether the character is masked with 0177 or 0377. ECHO /* echo all input */ Same name, in c_lflag. CTLECHO /* echo control chars as ^x */ Not in the USG driver, but it should be; call it ECHOCTL (just like CRTERASE is called ECHOE(!)) and put it in c_lflag. CBREAK /* wake up on all input */ Turn off ICANON (canonical input - erase and kill processing) in c_lflag. the usual tab, CR, NL, FF delay/expansion They are much the same, and are in c_oflag. All that processing can be efficiently turned off by turning off OPOST (postprocess output) in c_oflag - characters are moved from user space to the clist as directly as possible. ECHONL /* Echo NL after CR, for half-duplex with ~ECHO */ It's there, even under the same name, in c_lflag. BREAKNULL /* Change BREAK to null instead of sending signal */ Turn off IGNBRK (ignore breaks), BRKINT (send SIGINT on breaks), and PARMRK (mark parity errors framing errors, and overruns with "\377\000" in the input stream) in c_iflag. BREAKIGN /* Ignore BREAK completely */ Turn on IGNBRK in c_iflag. Note that the handling of a break in V7, at least, is a bit of a kludge; it pretends that it received your interrupt character (actually, the code is buggy and it pretends it received a RUBOUT) and hands it to ttyinput(). The USG driver handles it separately, so even if you turn off your interrupt and quit characters you can still send a SIGINT to your process by hitting the BREAK key. and all the special characters in one structure. Which they are. If you set neither, then BREAK should generate SIGINT in ANY mode. Which it does. End of commercial, but it would be nice, considering 4.2BSD has already adopted the USG "open" system call, if the people at Berkeley would consider adopting an enhanced version of the USG tty driver (including all their additional modes and control characters) for 4.2BSD or a later release. Note that the "ioctl" calls have different names - the modes are set by TCSETA - so the old calls could be kept around for compatibility. There are such backward compatibility features in the USG driver, but unfortunately for those of us not within AT&T they're backwards compatible with UNIX/TS 1.0 rather than with V7 or 4.1BSD. I can't see any legal arguments against it, since they've already put the USG "open" system call in (and since you get the System III C compiler, the PWB/UNIX 2.0? UUCP, the System IV? "sdb", "efl", and two pieces of the Writer's Workbench with 4.1BSD), and the only technical argument I can see against it (assuming the old "ioctl"s are left in for backward compatibility) is that it would take time to design and implement. And it would probably reduce the number of complaints about "I can't do this with the vanilla TTY driver" nearly to zero; you can even talk to Baudot lines (doing your own translation in your program) if you want. Guy Harris RLG Corporation {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy