]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.tty.c
Hack is now BSD-licensed. Thanks to Andries Brouwer, Jay Fenlason and
[bsdgames-darwin.git] / hack / hack.tty.c
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 }