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