xref: /openbsd/games/hack/hack.tty.c (revision df930be7)
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.5 1995/04/29 01:08:54 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 speed_t 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