wcs@ho95b.UUCP (Bill Stewart) (05/03/85)
/* * Here is hack.tty.c, modified to work on System V Release 2. * I haven't checked to see if it will still work on BSD, but it should. * Bill */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.tty.c - version 1.0.2 */ /* hacked by bill stewart at att-bl because the CBREAK flag doesn't work */ /* on System V - so I hacked it to use termio instead */ #include "hack.h" #include <stdio.h> #include <ctype.h> /* for isprint() */ #ifdef BSD #include <sgtty.h> #else #include <termio.h> #define sgttyb termio #define sg_flags c_lflag /* Well, most of the time it's used for c_lflag */ /* Yes, I admit it's crude */ #define CBREAK ICANON /* Usually you just care about the bitmask */ #endif BSD struct sgttyb inittyb, curttyb; extern short ospeed; char erase_char, kill_char; static boolean settty_needed = FALSE; #ifndef BSD unsigned char c_cc_VMIN, c_cc_VTIME; /* = c_cc[EOF] and c_cc[EOL] */ #endif /* * Get initial state of terminal, set ospeed (for termcap routines) * and switch off tab expansion if necessary. * Called by startup() in termcap.c and after returning from ! or ^Z */ gettty(){ #ifdef BSD (void) gtty(0, &inittyb); (void) gtty(0, &curttyb); ospeed = inittyb.sg_ospeed; erase_char = inittyb.sg_erase; kill_char = inittyb.sg_kill; getioctls(); #else (void) ioctl(0, TCGETA, &inittyb); (void) ioctl(0, TCGETA, &curttyb); ospeed = inittyb.c_cflag & CBAUD; erase_char = inittyb.c_cc[VERASE]; kill_char = inittyb.c_cc[VKILL]; getioctls(); #endif /* do not expand tabs - they might be needed inside a cm sequence */ #ifdef BSD if(curttyb.sg_flags & XTABS) { curttyb.sg_flags &= ~XTABS; #else if(curttyb.c_oflag & TAB3) { curttyb.c_oflag &= ~TAB3; #endif BSD setctty(); } settty_needed = TRUE; } /* fatal error */ /*VARARGS1*/ error(s,x,y) char *s; { if(settty_needed) settty((char *) 0); printf(s,x,y); putchar('\n'); exit(1); } /* reset terminal to original state */ settty(s) char *s; { clear_screen(); end_screen(); if(s) printf(s); (void) fflush(stdout); #ifdef BSD if(stty(0, &inittyb) == -1) #else if(ioctl(0, TCSETA, &inittyb) == -1) #endif BSD puts("Cannot change tty"); flags.echo = (inittyb.sg_flags & ECHO) ? ON : OFF; #ifdef BSD flags.cbreak = (inittyb.sg_flags & CBREAK) ? ON : OFF; #else flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON; #endif setioctls(); } setctty(){ #ifdef BSD if(stty(0, &curttyb) == -1) puts("Cannot change tty"); #else if(ioctl(0, TCSETA, &curttyb) == -1) puts("Cannot change tty"); #endif BSD } setftty(){ flags.cbreak = ON; flags.echo = OFF; setxtty(); } setxtty(){ register int ef = (flags.echo == ON) ? ECHO : 0; #ifdef BSD register int cf = (flags.cbreak == ON) ? CBREAK : 0; #else register int cf = (flags.cbreak == ON) ? 0 : ICANON; #endif register int change = 0; /* Should use (ECHO|CRMOD) here instead of ECHO */ if((curttyb.sg_flags & ECHO) != ef){ curttyb.sg_flags &= ~ECHO; curttyb.sg_flags |= ef; change++; } #ifdef BSD if((curttyb.sg_flags & CBREAK) != cf){ curttyb.sg_flags &= ~CBREAK; #else if((curttyb.sg_flags & ICANON || curttyb.c_cc[VMIN] > 1 ) != cf){ curttyb.sg_flags &= ~ICANON; curttyb.c_cc[VMIN] = (char) 1; /* Characters in a read() */ curttyb.c_cc[VTIME] = (char) 0; /* No timeout on a read() */ #endif BSD curttyb.sg_flags |= cf; change++; } if(change){ setctty(); } start_screen(); } /* * Read a line closed with '\n' into the array char bufp[BUFSZ]. * (The '\n' is not stored. The string is closed with a '\0'.) * Reading can be interrupted by an escape ('\033') - now the * resulting string is "\033". */ getlin(bufp) register char *bufp; { register char *obufp = bufp; register int c; flags.toplin = 2; /* nonempty, no --More-- required */ for(;;) { (void) fflush(stdout); if((c = getchar()) == EOF) { *bufp = 0; return; } if(c == '\033') { *obufp = c; obufp[1] = 0; return; } if(c == erase_char || c == '\b') { if(bufp != obufp) { bufp--; putstr("\b \b"); /* putsym converts \b */ } else bell(); } else if(c == '\n') { *bufp = 0; return; } else if(c == kill_char || c == '\177') { /* Robert Viduya */ while(bufp != obufp) { bufp--; putstr("\b \b"); } } else if(isprint(c)) { *bufp = c; bufp[1] = 0; putstr(bufp); if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) bufp++; } else bell(); } } getret() { xgetret(""); } cgetret(s) register char *s; { xgetret(s); } xgetret(s) register char *s; { putsym('\n'); if(flags.standout) standoutbeg(); putstr("Hit "); putstr(flags.cbreak ? "space" : "return"); putstr(" to continue: "); if(flags.standout) standoutend(); xwaitforspace(s); } char morc; /* tell the outside world what char he used */ xwaitforspace(s) register char *s; /* chars allowed besides space or return */ { register int c; (void) fflush(stdout); morc = 0; while((c = getchar()) != '\n') { if(c == EOF) end_of_input(); if(flags.cbreak) { if(c == ' ') break; if(s && index(s,c)) { morc = c; break; } bell(); /* useless if !cbreak */ } } } char * parse() { static char inline[COLNO]; register foo; flags.move = 1; if(!Invis) curs_on_u(); else home(); (void) fflush(stdout); while((foo = getchar()) >= '0' && foo <= '9') multi += 10*multi+foo-'0'; if(multi) { multi--; save_cm = inline; } inline[0] = foo; inline[1] = 0; if(foo == EOF) end_of_input(); if(foo == 'f' || foo == 'F'){ inline[1] = getchar(); #ifdef QUEST if(inline[1] == foo) inline[2] = getchar(); else #endif QUEST inline[2] = 0; } if(foo == 'm' || foo == 'M'){ inline[1] = getchar(); inline[2] = 0; } clrlin(); return(inline); } char readchar() { register int sym; (void) fflush(stdout); if((sym = getchar()) == EOF) end_of_input(); if(flags.toplin == 1) flags.toplin = 2; return((char) sym); } end_of_input() { settty("End of input?\n"); clearlocks(); exit(0); } -- Bill Stewart 1-201-949-0705 AT&T Bell Labs, Room 4K-435, Holmdel NJ {ihnp4,allegra,cbosgd,vax135}!ho95c!wcs
guy@sun.uucp (Guy Harris) (05/04/85)
> #ifdef BSD This should be "#ifdef V7"; it's not the BSD driver that's being used, it's the V7 driver (the BSD driver is a V7 superset). > #define CBREAK ICANON Nope. Turning CBREAK *on* is equivalent to turning ICANON off. However, the later code doesn't use CBREAK for the USDL driver, and does recognize that the sense of the bit is reversed, so this may not be a problem. > #ifdef BSD > register int cf = (flags.cbreak == ON) ? CBREAK : 0; > #else > register int cf = (flags.cbreak == ON) ? 0 : ICANON; > #endif > ... > #ifdef BSD > if((curttyb.sg_flags & CBREAK) != cf){ > curttyb.sg_flags &= ~CBREAK; > #else > if((curttyb.sg_flags & ICANON || curttyb.c_cc[VMIN] > 1 ) != cf){ I'd remove the test of c_cc[VMIN] if I were you - the appearance of the "||" means that the LHS of the comparison will be 1 or 0, but the RHS is "cf" which is either ICANON or 0 - ICANON is, if I remember correctly, 2 not 1. Other than that, it looks sane. Guy Harris