]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.tty.c
Refer to 'O' rather than 'o' as command to set options. Bug reported
[bsdgames-darwin.git] / hack / hack.tty.c
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@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 }