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