]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.tty.c
Need <stdlib.h> for abort() prototype.
[bsdgames-darwin.git] / hack / hack.tty.c
1 /* $NetBSD: hack.tty.c,v 1.10 2002/05/26 00:12:12 wiz 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.10 2002/05/26 00:12:12 wiz Exp $");
42 #endif
43 #endif /* not lint */
44
45 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
46 /* hack.tty.c - version 1.0.3 */
47 /*
48 * With thanks to the people who sent code for SYSV - hpscdi!jon,
49 * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
50 */
51
52 #include <termios.h>
53 #include <termcap.h>
54 #include "hack.h"
55 #include "extern.h"
56
57 /*
58 * Some systems may have getchar() return EOF for various reasons, and
59 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
60 */
61 #ifndef BSD
62 #define NR_OF_EOFS 20
63 #endif /* BSD */
64
65 static char erase_char, kill_char;
66 static boolean settty_needed = FALSE;
67 struct termios inittyb, curttyb;
68
69 /*
70 * Get initial state of terminal, set ospeed (for termcap routines)
71 * and switch off tab expansion if necessary.
72 * Called by startup() in termcap.c and after returning from ! or ^Z
73 */
74 void
75 gettty()
76 {
77 if (tcgetattr(0, &inittyb) < 0)
78 perror("Hack (gettty)");
79 curttyb = inittyb;
80 ospeed = cfgetospeed(&inittyb);
81 erase_char = inittyb.c_cc[VERASE];
82 kill_char = inittyb.c_cc[VKILL];
83 getioctls();
84
85 /* do not expand tabs - they might be needed inside a cm sequence */
86 if (curttyb.c_oflag & OXTABS) {
87 curttyb.c_oflag &= ~OXTABS;
88 setctty();
89 }
90 settty_needed = TRUE;
91 }
92
93 /* reset terminal to original state */
94 void
95 settty(s)
96 const char *s;
97 {
98 clear_screen();
99 end_screen();
100 if (s)
101 printf("%s", s);
102 (void) fflush(stdout);
103 if (tcsetattr(0, TCSADRAIN, &inittyb) < 0)
104 perror("Hack (settty)");
105 flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
106 flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
107 setioctls();
108 }
109
110 void
111 setctty()
112 {
113 if (tcsetattr(0, TCSADRAIN, &curttyb) < 0)
114 perror("Hack (setctty)");
115 }
116
117
118 void
119 setftty()
120 {
121 int change = 0;
122 flags.cbreak = ON;
123 flags.echo = OFF;
124 /* Should use (ECHO|CRMOD) here instead of ECHO */
125 if (curttyb.c_lflag & ECHO) {
126 curttyb.c_lflag &= ~ECHO;
127 change++;
128 }
129 if (curttyb.c_lflag & ICANON) {
130 curttyb.c_lflag &= ~ICANON;
131 /* be satisfied with one character; no timeout */
132 curttyb.c_cc[VMIN] = 1;
133 curttyb.c_cc[VTIME] = 0;
134 change++;
135 }
136 if (change) {
137 setctty();
138 }
139 start_screen();
140 }
141
142
143 /* fatal error */
144 /* VARARGS1 */
145 void
146 error(const char *fmt, ...)
147 {
148 va_list ap;
149
150 va_start(ap, fmt);
151 if (settty_needed)
152 settty((char *) 0);
153 vprintf(fmt, ap);
154 va_end(ap);
155 putchar('\n');
156 exit(1);
157 }
158
159 /*
160 * Read a line closed with '\n' into the array char bufp[BUFSZ].
161 * (The '\n' is not stored. The string is closed with a '\0'.)
162 * Reading can be interrupted by an escape ('\033') - now the
163 * resulting string is "\033".
164 */
165 void
166 getlin(bufp)
167 char *bufp;
168 {
169 char *obufp = bufp;
170 int c;
171
172 flags.toplin = 2; /* nonempty, no --More-- required */
173 for (;;) {
174 (void) fflush(stdout);
175 if ((c = getchar()) == EOF) {
176 *bufp = 0;
177 return;
178 }
179 if (c == '\033') {
180 *obufp = c;
181 obufp[1] = 0;
182 return;
183 }
184 if (c == erase_char || c == '\b') {
185 if (bufp != obufp) {
186 bufp--;
187 putstr("\b \b"); /* putsym converts \b */
188 } else
189 bell();
190 } else if (c == '\n') {
191 *bufp = 0;
192 return;
193 } else if (' ' <= c && c < '\177') {
194 /*
195 * avoid isprint() - some people don't have it ' ' is
196 * not always a printing char
197 */
198 *bufp = c;
199 bufp[1] = 0;
200 putstr(bufp);
201 if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)
202 bufp++;
203 } else if (c == kill_char || c == '\177') { /* Robert Viduya */
204 /* this test last - @ might be the kill_char */
205 while (bufp != obufp) {
206 bufp--;
207 putstr("\b \b");
208 }
209 } else
210 bell();
211 }
212 }
213
214 void
215 getret()
216 {
217 cgetret("");
218 }
219
220 void
221 cgetret(s)
222 const char *s;
223 {
224 putsym('\n');
225 if (flags.standout)
226 standoutbeg();
227 putstr("Hit ");
228 putstr(flags.cbreak ? "space" : "return");
229 putstr(" to continue: ");
230 if (flags.standout)
231 standoutend();
232 xwaitforspace(s);
233 }
234
235 char morc; /* tell the outside world what char he used */
236
237 void
238 xwaitforspace(s)
239 const char *s; /* chars allowed besides space or return */
240 {
241 int c;
242
243 morc = 0;
244
245 while ((c = readchar()) != '\n') {
246 if (flags.cbreak) {
247 if (c == ' ')
248 break;
249 if (s && strchr(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 int foo;
263
264 flags.move = 1;
265 if (!Invisible)
266 curs_on_u();
267 else
268 home();
269 while ((foo = readchar()) >= '0' && foo <= '9')
270 multi = 10 * multi + foo - '0';
271 if (multi) {
272 multi--;
273 save_cm = inputline;
274 }
275 inputline[0] = foo;
276 inputline[1] = 0;
277 if (foo == 'f' || foo == 'F') {
278 inputline[1] = getchar();
279 #ifdef QUEST
280 if (inputline[1] == foo)
281 inputline[2] = getchar();
282 else
283 #endif /* QUEST */
284 inputline[2] = 0;
285 }
286 if (foo == 'm' || foo == 'M') {
287 inputline[1] = getchar();
288 inputline[2] = 0;
289 }
290 clrlin();
291 return (inputline);
292 }
293
294 char
295 readchar()
296 {
297 int sym;
298
299 (void) fflush(stdout);
300 if ((sym = getchar()) == EOF)
301 #ifdef NR_OF_EOFS
302 { /*
303 * Some SYSV systems seem to return EOFs for various reasons
304 * (?like when one hits break or for interrupted systemcalls?),
305 * and we must see several before we quit.
306 */
307 int cnt = NR_OF_EOFS;
308 while (cnt--) {
309 clearerr(stdin); /* omit if clearerr is
310 * undefined */
311 if ((sym = getchar()) != EOF)
312 goto noteof;
313 }
314 end_of_input();
315 noteof: ;
316 }
317 #else
318 end_of_input();
319 #endif /* NR_OF_EOFS */
320 if (flags.toplin == 1)
321 flags.toplin = 2;
322 return ((char) sym);
323 }
324
325 void
326 end_of_input()
327 {
328 settty("End of input?\n");
329 clearlocks();
330 exit(0);
331 }