xref: /netbsd-src/games/hack/hack.tty.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
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@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