xref: /original-bsd/games/hack/hack.tty.c (revision 50dd0bba)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)hack.tty.c	5.2 (Berkeley) 07/22/88";
20 #endif /* not lint */
21 
22 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
23 /* hack.tty.c - version 1.0.3 */
24 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
25    arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
26 
27 #include	"hack.h"
28 #include	<stdio.h>
29 
30 /*
31  * The distinctions here are not BSD - rest but rather USG - rest, as
32  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
33  */
34 #ifdef BSD
35 #define	V7
36 #else
37 #define USG
38 #endif BSD
39 
40 /*
41  * Some systems may have getchar() return EOF for various reasons, and
42  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
43  */
44 #ifndef BSD
45 #define	NR_OF_EOFS	20
46 #endif BSD
47 
48 
49 #ifdef USG
50 
51 #include	<termio.h>
52 #define termstruct	termio
53 #define kill_sym	c_cc[VKILL]
54 #define erase_sym	c_cc[VERASE]
55 #define EXTABS		TAB3
56 #define tabflgs		c_oflag
57 #define echoflgs	c_lflag
58 #define cbrkflgs	c_lflag
59 #define CBRKMASK	ICANON
60 #define CBRKON		! /* reverse condition */
61 #define OSPEED(x)	((x).c_cflag & CBAUD)
62 #define GTTY(x)		(ioctl(0, TCGETA, x))
63 #define STTY(x)		(ioctl(0, TCSETA, x))	/* TCSETAF? TCSETAW? */
64 
65 #else	/* V7 */
66 
67 #include	<sgtty.h>
68 #define termstruct	sgttyb
69 #define	kill_sym	sg_kill
70 #define	erase_sym	sg_erase
71 #define EXTABS		XTABS
72 #define tabflgs		sg_flags
73 #define echoflgs	sg_flags
74 #define cbrkflgs	sg_flags
75 #define CBRKMASK	CBREAK
76 #define CBRKON		/* empty */
77 #define OSPEED(x)	(x).sg_ospeed
78 #define GTTY(x)		(gtty(0, x))
79 #define STTY(x)		(stty(0, x))
80 
81 #endif USG
82 
83 extern short ospeed;
84 static char erase_char, kill_char;
85 static boolean settty_needed = FALSE;
86 struct termstruct inittyb, curttyb;
87 
88 /*
89  * Get initial state of terminal, set ospeed (for termcap routines)
90  * and switch off tab expansion if necessary.
91  * Called by startup() in termcap.c and after returning from ! or ^Z
92  */
93 gettty(){
94 	if(GTTY(&inittyb) < 0)
95 		perror("Hack (gettty)");
96 	curttyb = inittyb;
97 	ospeed = OSPEED(inittyb);
98 	erase_char = inittyb.erase_sym;
99 	kill_char = inittyb.kill_sym;
100 	getioctls();
101 
102 	/* do not expand tabs - they might be needed inside a cm sequence */
103 	if(curttyb.tabflgs & EXTABS) {
104 		curttyb.tabflgs &= ~EXTABS;
105 		setctty();
106 	}
107 	settty_needed = TRUE;
108 }
109 
110 /* reset terminal to original state */
111 settty(s) char *s; {
112 	clear_screen();
113 	end_screen();
114 	if(s) printf(s);
115 	(void) fflush(stdout);
116 	if(STTY(&inittyb) < 0)
117 		perror("Hack (settty)");
118 	flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
119 	flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
120 	setioctls();
121 }
122 
123 setctty(){
124 	if(STTY(&curttyb) < 0)
125 		perror("Hack (setctty)");
126 }
127 
128 
129 setftty(){
130 register int ef = 0;			/* desired value of flags & ECHO */
131 register int cf = CBRKON(CBRKMASK);	/* desired value of flags & CBREAK */
132 register int change = 0;
133 	flags.cbreak = ON;
134 	flags.echo = OFF;
135 	/* Should use (ECHO|CRMOD) here instead of ECHO */
136 	if((curttyb.echoflgs & ECHO) != ef){
137 		curttyb.echoflgs &= ~ECHO;
138 /*		curttyb.echoflgs |= ef;					*/
139 		change++;
140 	}
141 	if((curttyb.cbrkflgs & CBRKMASK) != cf){
142 		curttyb.cbrkflgs &= ~CBRKMASK;
143 		curttyb.cbrkflgs |= cf;
144 #ifdef USG
145 		/* be satisfied with one character; no timeout */
146 		curttyb.c_cc[VMIN] = 1;		/* was VEOF */
147 		curttyb.c_cc[VTIME] = 0;	/* was VEOL */
148 #endif USG
149 		change++;
150 	}
151 	if(change){
152 		setctty();
153 	}
154 	start_screen();
155 }
156 
157 
158 /* fatal error */
159 /*VARARGS1*/
160 error(s,x,y) char *s; {
161 	if(settty_needed)
162 		settty((char *) 0);
163 	printf(s,x,y);
164 	putchar('\n');
165 	exit(1);
166 }
167 
168 /*
169  * Read a line closed with '\n' into the array char bufp[BUFSZ].
170  * (The '\n' is not stored. The string is closed with a '\0'.)
171  * Reading can be interrupted by an escape ('\033') - now the
172  * resulting string is "\033".
173  */
174 getlin(bufp)
175 register char *bufp;
176 {
177 	register char *obufp = bufp;
178 	register int c;
179 
180 	flags.toplin = 2;		/* nonempty, no --More-- required */
181 	for(;;) {
182 		(void) fflush(stdout);
183 		if((c = getchar()) == EOF) {
184 			*bufp = 0;
185 			return;
186 		}
187 		if(c == '\033') {
188 			*obufp = c;
189 			obufp[1] = 0;
190 			return;
191 		}
192 		if(c == erase_char || c == '\b') {
193 			if(bufp != obufp) {
194 				bufp--;
195 				putstr("\b \b"); /* putsym converts \b */
196 			} else	bell();
197 		} else if(c == '\n') {
198 			*bufp = 0;
199 			return;
200 		} else if(' ' <= c && c < '\177') {
201 				/* avoid isprint() - some people don't have it
202 				   ' ' is not always a printing char */
203 			*bufp = c;
204 			bufp[1] = 0;
205 			putstr(bufp);
206 			if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
207 				bufp++;
208 		} else if(c == kill_char || c == '\177') { /* Robert Viduya */
209 				/* this test last - @ might be the kill_char */
210 			while(bufp != obufp) {
211 				bufp--;
212 				putstr("\b \b");
213 			}
214 		} else
215 			bell();
216 	}
217 }
218 
219 getret() {
220 	cgetret("");
221 }
222 
223 cgetret(s)
224 register char *s;
225 {
226 	putsym('\n');
227 	if(flags.standout)
228 		standoutbeg();
229 	putstr("Hit ");
230 	putstr(flags.cbreak ? "space" : "return");
231 	putstr(" to continue: ");
232 	if(flags.standout)
233 		standoutend();
234 	xwaitforspace(s);
235 }
236 
237 char morc;	/* tell the outside world what char he used */
238 
239 xwaitforspace(s)
240 register char *s;	/* chars allowed besides space or return */
241 {
242 register int c;
243 
244 	morc = 0;
245 
246 	while((c = readchar()) != '\n') {
247 	    if(flags.cbreak) {
248 		if(c == ' ') break;
249 		if(s && index(s,c)) {
250 			morc = c;
251 			break;
252 		}
253 		bell();
254 	    }
255 	}
256 }
257 
258 char *
259 parse()
260 {
261 	static char inputline[COLNO];
262 	register foo;
263 
264 	flags.move = 1;
265 	if(!Invisible) curs_on_u(); else home();
266 	while((foo = readchar()) >= '0' && foo <= '9')
267 		multi = 10*multi+foo-'0';
268 	if(multi) {
269 		multi--;
270 		save_cm = inputline;
271 	}
272 	inputline[0] = foo;
273 	inputline[1] = 0;
274 	if(foo == 'f' || foo == 'F'){
275 		inputline[1] = getchar();
276 #ifdef QUEST
277 		if(inputline[1] == foo) inputline[2] = getchar(); else
278 #endif QUEST
279 		inputline[2] = 0;
280 	}
281 	if(foo == 'm' || foo == 'M'){
282 		inputline[1] = getchar();
283 		inputline[2] = 0;
284 	}
285 	clrlin();
286 	return(inputline);
287 }
288 
289 char
290 readchar() {
291 	register int sym;
292 
293 	(void) fflush(stdout);
294 	if((sym = getchar()) == EOF)
295 #ifdef NR_OF_EOFS
296 	{ /*
297 	   * Some SYSV systems seem to return EOFs for various reasons
298 	   * (?like when one hits break or for interrupted systemcalls?),
299 	   * and we must see several before we quit.
300 	   */
301 		register int cnt = NR_OF_EOFS;
302 		while (cnt--) {
303 		    clearerr(stdin);	/* omit if clearerr is undefined */
304 		    if((sym = getchar()) != EOF) goto noteof;
305 		}
306 		end_of_input();
307 	     noteof:	;
308 	}
309 #else
310 		end_of_input();
311 #endif NR_OF_EOFS
312 	if(flags.toplin == 1)
313 		flags.toplin = 2;
314 	return((char) sym);
315 }
316 
317 end_of_input()
318 {
319 	settty("End of input?\n");
320 	clearlocks();
321 	exit(0);
322 }
323