Home | History | Annotate | Line # | Download | only in hack
hack.tty.c revision 1.4
      1 /*-
      2  * Copyright (c) 1988, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 #if 0
     36 static char sccsid[] = "@(#)hack.tty.c	8.1 (Berkeley) 5/31/93";
     37 #else
     38 static char rcsid[] = "$NetBSD: hack.tty.c,v 1.4 1995/04/28 23:01:47 mycroft Exp $";
     39 #endif
     40 #endif /* not lint */
     41 
     42 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
     43 /* hack.tty.c - version 1.0.3 */
     44 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
     45    arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
     46 
     47 #include	"hack.h"
     48 #include	<stdio.h>
     49 #include	<termios.h>
     50 
     51 /*
     52  * Some systems may have getchar() return EOF for various reasons, and
     53  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
     54  */
     55 #ifndef BSD
     56 #define	NR_OF_EOFS	20
     57 #endif BSD
     58 
     59 extern short ospeed;
     60 static char erase_char, kill_char;
     61 static boolean settty_needed = FALSE;
     62 struct termios inittyb, curttyb;
     63 
     64 /*
     65  * Get initial state of terminal, set ospeed (for termcap routines)
     66  * and switch off tab expansion if necessary.
     67  * Called by startup() in termcap.c and after returning from ! or ^Z
     68  */
     69 gettty(){
     70 	if(tcgetattr(0, &inittyb) < 0)
     71 		perror("Hack (gettty)");
     72 	curttyb = inittyb;
     73 	ospeed = cfgetospeed(&inittyb);
     74 	erase_char = inittyb.c_cc[VERASE];
     75 	kill_char = inittyb.c_cc[VKILL];
     76 	getioctls();
     77 
     78 	/* do not expand tabs - they might be needed inside a cm sequence */
     79 	if(curttyb.c_oflag & OXTABS) {
     80 		curttyb.c_oflag &= ~OXTABS;
     81 		setctty();
     82 	}
     83 	settty_needed = TRUE;
     84 }
     85 
     86 /* reset terminal to original state */
     87 settty(s) char *s; {
     88 	clear_screen();
     89 	end_screen();
     90 	if(s) printf(s);
     91 	(void) fflush(stdout);
     92 	if(tcsetattr(0, TCSADRAIN, &inittyb) < 0)
     93 		perror("Hack (settty)");
     94 	flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
     95 	flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
     96 	setioctls();
     97 }
     98 
     99 setctty(){
    100 	if(tcsetattr(0, TCSADRAIN, &curttyb) < 0)
    101 		perror("Hack (setctty)");
    102 }
    103 
    104 
    105 setftty(){
    106 register int change = 0;
    107 	flags.cbreak = ON;
    108 	flags.echo = OFF;
    109 	/* Should use (ECHO|CRMOD) here instead of ECHO */
    110 	if(curttyb.c_lflag & ECHO){
    111 		curttyb.c_lflag &= ~ECHO;
    112 		change++;
    113 	}
    114 	if(curttyb.c_lflag & ICANON){
    115 		curttyb.c_lflag &= ~ICANON;
    116 		/* be satisfied with one character; no timeout */
    117 		curttyb.c_cc[VMIN] = 1;
    118 		curttyb.c_cc[VTIME] = 0;
    119 		change++;
    120 	}
    121 	if(change){
    122 		setctty();
    123 	}
    124 	start_screen();
    125 }
    126 
    127 
    128 /* fatal error */
    129 /*VARARGS1*/
    130 error(s,x,y) char *s; {
    131 	if(settty_needed)
    132 		settty((char *) 0);
    133 	printf(s,x,y);
    134 	putchar('\n');
    135 	exit(1);
    136 }
    137 
    138 /*
    139  * Read a line closed with '\n' into the array char bufp[BUFSZ].
    140  * (The '\n' is not stored. The string is closed with a '\0'.)
    141  * Reading can be interrupted by an escape ('\033') - now the
    142  * resulting string is "\033".
    143  */
    144 getlin(bufp)
    145 register char *bufp;
    146 {
    147 	register char *obufp = bufp;
    148 	register int c;
    149 
    150 	flags.toplin = 2;		/* nonempty, no --More-- required */
    151 	for(;;) {
    152 		(void) fflush(stdout);
    153 		if((c = getchar()) == EOF) {
    154 			*bufp = 0;
    155 			return;
    156 		}
    157 		if(c == '\033') {
    158 			*obufp = c;
    159 			obufp[1] = 0;
    160 			return;
    161 		}
    162 		if(c == erase_char || c == '\b') {
    163 			if(bufp != obufp) {
    164 				bufp--;
    165 				putstr("\b \b"); /* putsym converts \b */
    166 			} else	bell();
    167 		} else if(c == '\n') {
    168 			*bufp = 0;
    169 			return;
    170 		} else if(' ' <= c && c < '\177') {
    171 				/* avoid isprint() - some people don't have it
    172 				   ' ' is not always a printing char */
    173 			*bufp = c;
    174 			bufp[1] = 0;
    175 			putstr(bufp);
    176 			if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
    177 				bufp++;
    178 		} else if(c == kill_char || c == '\177') { /* Robert Viduya */
    179 				/* this test last - @ might be the kill_char */
    180 			while(bufp != obufp) {
    181 				bufp--;
    182 				putstr("\b \b");
    183 			}
    184 		} else
    185 			bell();
    186 	}
    187 }
    188 
    189 getret() {
    190 	cgetret("");
    191 }
    192 
    193 cgetret(s)
    194 register char *s;
    195 {
    196 	putsym('\n');
    197 	if(flags.standout)
    198 		standoutbeg();
    199 	putstr("Hit ");
    200 	putstr(flags.cbreak ? "space" : "return");
    201 	putstr(" to continue: ");
    202 	if(flags.standout)
    203 		standoutend();
    204 	xwaitforspace(s);
    205 }
    206 
    207 char morc;	/* tell the outside world what char he used */
    208 
    209 xwaitforspace(s)
    210 register char *s;	/* chars allowed besides space or return */
    211 {
    212 register int c;
    213 
    214 	morc = 0;
    215 
    216 	while((c = readchar()) != '\n') {
    217 	    if(flags.cbreak) {
    218 		if(c == ' ') break;
    219 		if(s && index(s,c)) {
    220 			morc = c;
    221 			break;
    222 		}
    223 		bell();
    224 	    }
    225 	}
    226 }
    227 
    228 char *
    229 parse()
    230 {
    231 	static char inputline[COLNO];
    232 	register foo;
    233 
    234 	flags.move = 1;
    235 	if(!Invisible) curs_on_u(); else home();
    236 	while((foo = readchar()) >= '0' && foo <= '9')
    237 		multi = 10*multi+foo-'0';
    238 	if(multi) {
    239 		multi--;
    240 		save_cm = inputline;
    241 	}
    242 	inputline[0] = foo;
    243 	inputline[1] = 0;
    244 	if(foo == 'f' || foo == 'F'){
    245 		inputline[1] = getchar();
    246 #ifdef QUEST
    247 		if(inputline[1] == foo) inputline[2] = getchar(); else
    248 #endif QUEST
    249 		inputline[2] = 0;
    250 	}
    251 	if(foo == 'm' || foo == 'M'){
    252 		inputline[1] = getchar();
    253 		inputline[2] = 0;
    254 	}
    255 	clrlin();
    256 	return(inputline);
    257 }
    258 
    259 char
    260 readchar() {
    261 	register int sym;
    262 
    263 	(void) fflush(stdout);
    264 	if((sym = getchar()) == EOF)
    265 #ifdef NR_OF_EOFS
    266 	{ /*
    267 	   * Some SYSV systems seem to return EOFs for various reasons
    268 	   * (?like when one hits break or for interrupted systemcalls?),
    269 	   * and we must see several before we quit.
    270 	   */
    271 		register int cnt = NR_OF_EOFS;
    272 		while (cnt--) {
    273 		    clearerr(stdin);	/* omit if clearerr is undefined */
    274 		    if((sym = getchar()) != EOF) goto noteof;
    275 		}
    276 		end_of_input();
    277 	     noteof:	;
    278 	}
    279 #else
    280 		end_of_input();
    281 #endif NR_OF_EOFS
    282 	if(flags.toplin == 1)
    283 		flags.toplin = 2;
    284 	return((char) sym);
    285 }
    286 
    287 end_of_input()
    288 {
    289 	settty("End of input?\n");
    290 	clearlocks();
    291 	exit(0);
    292 }
    293