/* 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" #include /* System V. Superceds sgtty.h*/ struct termio tmode,sv_tmode; 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; int xrows,xcols; extern char *getenv(); /* to keep the vax cc happy! -pls */ if (!setup_done) /* discover tty modes */ /* For sys V only */ ioctl(std_ter,TCGETA,&tmode); sv_tmode = tmode; /* turn off echo and canonical mode) */ tmode.c_lflag &= ~(ICANON | ECHO ); tmode.c_cc[VINTR] =03; /* Control-C */ tmode.c_cc[VQUIT] = 034; /*Control-shift-l. Quit */ /* We are now in Raw mode. In this mode CR does not satisfy reads by the device driver. We need to modify the line disipline by setting the minimum nuber of chars, and the elapsed time since last char input , which would satisfy the read*/ tmode.c_cc[VMIN]= 1; /* turn off cr mapping*/ tmode.c_iflag &= ~ICRNL; tmode.c_oflag &= ~(OCRNL|ONLCR|ONLRET); if (rowmap==0) /* first time in */ { /* set up teletype characteristics */ xrows=TER_ROWS; xcols=TER_COLS; if (streq(getenv("TERM"),"cifer") || streq(getenv("TERM"),"cf2605")) ter_setup(&cf05_ter); else if (streq(getenv("TERM"),"cf2634")) ter_setup(&cf34_ter); else if(streq(getenv("TERM"),"vt100")) ter_setup(&vt1_ter); else if (streq(getenv("TERM"),"cft2") || streq(getenv("TERM"),"t2")) ter_setup(&cfT2_ter); else if(streq(getenv("TERM"),"300h")) { ter_setup(&hp300_ter); xrows=46; xcols=128; } else editerror("unknown Terminal Type"); } if(Pswitch) { nrows=Prows; ncols=Pcols; } else { nrows=xrows; ncols=xcols; } if(ncols+1>ENOUGH) editerror("Screen size too wide (max %d Cols) [TTYSETUP]",ncols+1); else rowmap = newscreen(); /* dont setup auxscreen yet */ if (!Pswitch) ioctl(std_ter,TCSETAF,&tmode); /* 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 * unfortunately having it before stops you reading single char * status information from the vdu * suggest that there should be a *ter.setmode routine that is called * before the ioctl */ (*ter.setup)(); 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) ioctl(std_ter,TCSETA,&sv_tmode); 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(); }