/* tty.c: modified for Herriot-Watt tty driver 2/2/82 - PLS * (compile with -DH_WDRIVER for EUUG driver * " " -DQMCDRIVER for QMC driver * " " -DUMVDRIVER for UMIST Vax driver with paging * default .................... BELL or Berkeley driver) */ #include "ded.h" #include "char.h" #include "tty.h" #include "signal.h" #include "ter.h" /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ #include "SITE.def" /* mode-remembering stuff */ #ifdef V7 struct sgttyb tmode, sv_tmode; struct tchars tchars, sv_tchars; # if vax struct ltchars ltchars, sv_ltchars; # endif #else struct TTYMODE { char ispeed, ospeed, terase, kill; int flags; char nldelay, crdelay, tbdelay, vtdelay; char width, length; int brktab[8]; } tmode, sv_tmode; #endif ttyinterrupt() { signal(SIGINT, ttyinterrupt); ttyzonk(); intr_typed = true; } ttyzonk() { ttyinbuf.n_in = 0; ttyinbuf.nxch = ttyinbuf.tbuf; complain(); } /* find user's attitude without disturbing .dlog file */ char qread() { char c; ttyflush(); while (read(std_in,&c,1)!=1) ; return(c); } int query(str) char *str; { register char c; do { x_cdiag(&str); c=qread(); } while (c!='y' && c!='n'); return(c=='y'); } ttyquit() { signal(SIGQUIT, SIG_IGN); ttyzonk(); if (query("do you really want a core dump?")) { ttyreset(); abort(); } else { diag("I'll let you off this time, then"); signal(SIGQUIT, ttyquit); fixpos(); /* ttyflush(); */ } quit_typed = true; } /* variables to help in setting up interrupts */ int (*savquit)() = ttyquit, (*savintr)() = ttyinterrupt; /* start up funny tty mode */ ttysetup() { ttybuf.n_in = 0; ttybuf.nxch = ttybuf.tbuf; dlogbuf.n_in = 0; dlogbuf.nxch = dlogbuf.tbuf; ttyinbuf.n_in = 0; ttyinbuf.nxch = ttyinbuf.tbuf; ttysetmode(); } ttysetmode() { int tncols, tnrows; extern char *getenv(); /* to keep the vax cc happy! -pls */ if (!setup_done) /* discover tty modes */ #ifdef V7 { # if H_WDRIVER | UMVDRIVER ioctl(STD_TER, TIOCGETA, &tmode); # else ioctl(STD_TER, TIOCGETP, &tmode); /* old-style gtty */ # endif sv_tmode = tmode; tmode.sg_flags &= ~(RAW | CRMOD | ECHO | XTABS); # ifdef T_STARTC tmode.sg_flags |= (CBREAK | TANDEM); # else tmode.sg_flags |= CBREAK; # endif # if QMCDRIVER | H_WDRIVER | UMVDRIVER tncols = tmode.sg_width; tnrows = tmode.sg_length; tmode.sg_width = tmode.sg_length = 0; # endif # if H_WDRIVER tmode.sg_nldly = tmode.sg_crdly = tmode.sg_htdly = tmode.sg_vtdly = 0; # endif ioctl(STD_TER, TIOCGETC, &tchars); /* new-style get characters */ sv_tchars = tchars; tchars.t_intrc = 03; /* control-C */ tchars.t_quitc = 034; /* control-shift-L */ /* start and stop are terminal_dependent - there really exist * terminals which use handshaking */ # ifdef T_STARTC tchars.t_startc = T_STARTC; tchars.t_stopc = T_STOPC; tchars.t_eofc = tchars.t_brkc = -1; # else tchars.t_startc = tchars.t_stopc = tchars.t_eofc = tchars.t_brkc = -1; # endif # if vax ioctl(STD_TER, TIOCGLTC, <chars); /* more characters on vax */ sv_ltchars = ltchars; ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_rprntc = ltchars.t_flushc = ltchars.t_werasc = ltchars.t_lnextc = -1; # endif } #else /* under version 6 we always use the QMC driver - or at * least we have RARE mode */ { gterm(STD_TER, &tmode); sv_tmode = tmode; tmode.flags =& ~ (T_BITS | T_INDCTL | T_ECHO | T_TABS | T_CRLF); tmode.flags =| (T_RAW | T_RARE); tncols = tmode.width; tnrows = tmode.length; tmode.width = tmode.length = 0; } #endif if (rowmap==0) /* first time in */ { /* set up teletype characteristics */ #if QMCDRIVER | H_WDRIVER | UMVDRIVER if (Pswitch) { tnrows = Prows; tncols = Pcols; } #endif #ifdef V7 # ifdef QMC { char *t = getenv("TERM"); if (streq(t, N_QMC)) ter_setup(&qmc_ter); else if (streq(t, N_ITT)) ter_setup(&itt_ter); else /* no text terminal at present ... if (streq(t, N_TXT)) ter_setup(&txt_ter); else */ editerror("unknown terminal type %s - reset with stty", t); } # else (not QMC) # if UMIST | UMISTc | UMISTv | UMISTh | UMISTt { char *t = getenv("TERM"); # if UMIST | UMISTc if (streq(t,"cifer")) ter_setup(&cif_ter); else # endif # if UMIST | UMISTv if (streq(t,"vt100")) ter_setup(&vt1_ter); else # endif # if UMIST | UMISTh if (streq(t,"hazeltine")) ter_setup(&haz_ter); else # endif # if UMIST | UMISTt if (streq(t,"tek4023")) ter_setup(&tek_ter); else # endif # if vax if (streq(t,"sjs")) ter_setup(&sjs_ter); else # endif editerror("unknown terminal type %s - change $TERM in env.", t); } # else (not UMIST) # ifdef COMPU { char *t = getenv("TERM"); if (streq(t,"VT100")) ter_setup(&vt1_ter); else if (streq(t,"vt100")) ter_setup(&vt1_ter); else if (streq(t,"VT52")) ter_setup(&vt5_ter); else if (streq(t,"vt52")) ter_setup(&vt5_ter); else editerror("unknown terminal type %s - have you set $TERM ?", t); } # else (not COMPU) # ifdef BRISTOL { char *t = getenv("TERM"); if (streq(t,"vt100")) ter_setup(&vt1_ter); else if (streq(t,"dt22")) ter_setup(&dt2_ter); else editerror("unknown terminal type %s - have you set $TERM ?", t); } # else (not BRISTOL) ter_setup(&TER_TAB); # endif BRISTOL # endif COMPU # endif UMIST # endif QMC #else (V6) /* under version 6 we always use the QMC driver, of course */ # ifdef QMC { int tertype = sv_tmode.flags & T_BITS; if (tertype==T_TXT) ter_setup(&txt_ter); else if (tertype==T_ITT) ter_setup(&itt_ter); else if (tertype==T_QMC) ter_setup(&qmc_ter); else editerror("invalid terminal mode - reset with ter"); } # else (not QMC) ter_setup(&TER_TAB); # endif (QMC or not) #endif (V7 or not) #if QMCDRIVER | H_WDRIVER | UMVDRIVER if (tnrows<2 || tncolsENOUGH) editerror("screen size too wide (max %d cols) [ttysetup]", ENOUGH-1); else rowmap = newscreen(); /* don't set up auxscreen yet */ } /* do the things that are necessary to frig ded for this terminal * - moved from ter_setup (ter.c) so that it is called every time * ded is re-entered, in case any terminal setup sequences have * to be sent out. Done before tty modes are set, however, so * that modes can be changed on an individual terminal basis in * *ter.setup if necessary - PLS UMIST 20/12/83 */ (*ter.setup)(); if (!Pswitch) #ifdef V7 { # if H_WDRIVER | UMVDRIVER ioctl(STD_TER, TIOCSETA, &tmode); # else ioctl(STD_TER, TIOCSETN, &tmode); /* old-style stty */ # endif ioctl(STD_TER, TIOCSETC, &tchars); /* new-style set characters */ # if vax ioctl(STD_TER, TIOCSLTC, <chars); /* more for the vax */ # endif } #else sterm(STD_TER,&tmode); #endif setup_done=true; NINROWS = (nrows-1); LASTINROW = (nrows-2); EDITROW = (nrows-1); FOOTROW = (nrows-1); SCROLL = (nrows/3); RIGHTCOL = (ncols-1); signal(SIGQUIT, savquit); signal(SIGINT, savintr); } ttyreset() { ttyflush(); dlogflush(); /* turn off interrupts */ savquit = signal(SIGQUIT, SIG_IGN); savintr = signal(SIGINT, SIG_IGN); if (setup_done) { #ifdef V7 if (!Pswitch) { # if H_WDRIVER | UMVDRIVER ioctl(STD_TER, TIOCSETA, &sv_tmode); /* set mode */ # else ioctl(STD_TER, TIOCSETN, &sv_tmode); /* set mode */ # endif ioctl(STD_TER, TIOCSETC, &sv_tchars); /* set characters */ # if vax ioctl(STD_TER, TIOCSLTC, &sv_ltchars); /* more for the vax */ # endif } #else if (!Pswitch) sterm(STD_TER,&sv_tmode); #endif } if (ter.restore) (*ter.restore)(); /* UMIST */ ttyflush(); setup_done=false; } /* stuff characters in buffer, to save too many system calls */ ttyout(c) register int c; { if (ttybuf.n_in >= TTYBUFSIZE) ttyflush(); if (c&0200 && sendseq(ter.vidseq.bright)) /* top bit set - display bright if possible */ { ttyout(c&0177); sendseq(ter.vidseq.normal); /* must be one of these! */ } else { *(ttybuf.nxch++) = (c&0177); ttybuf.n_in++; } } /* empty buffer */ ttyflush() { bufflush(&ttybuf, std_out); } dlogflush() { if (bufflush(&dlogbuf, dlogger) < 0) { dlogbuf.n_in = 0; editerror("[dlogflush] dlogwrite failed - not enough space?"); } } bufflush(abuf, chan) register struct TTYBUF *abuf; register int chan; { register int count; if ((count = abuf->n_in) != 0) { if (write(chan, abuf->tbuf, count) != count) return(-1); abuf->nxch = abuf->tbuf; abuf->n_in=0; } return(1); } /* a procedure to read in from the teletype and record * each character in the .dlog file */ ttyin() { register int count, input; register char c; input = tty_input; while (--ttyinbuf.n_in < 0) { count = (input==dlogger ? TTYBUFSIZE : mode==EDMODE ? 1 : 3); ttyflush(); /* don't do it unless waiting for input */ if ((count=read(input,ttyinbuf.tbuf,count))<=0 && input==dlogger) { input=tty_input=std_in; /* end of dlog input */ diag("** end of %s **", dlogname); fixpos(); return(0); /* if anyone wants it */ } ttyinbuf.n_in = count; ttyinbuf.nxch = ttyinbuf.tbuf; } c = *(ttyinbuf.nxch++); if (input!=dlogger) dlogout(c); return(c); } /* put a character in the dlog file */ dlogout(c) register char c; { if (dlogbuf.n_in >= TTYBUFSIZE) dlogflush(); *(dlogbuf.nxch++) = c; dlogbuf.n_in++; if ((c<040 || c==0177) && dlogbuf.n_in>10) dlogflush(); }