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