periodic(8): Sync with FreeBSD current
[dragonfly.git] / games / hack / hack.tty.c
blob37f12bf48c927926d0e1caf36f5140aa12643f89
1 /*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#)hack.tty.c 8.1 (Berkeley) 5/31/93
30 * $FreeBSD: src/games/hack/hack.tty.c,v 1.6.2.1 2000/07/20 10:35:07 kris Exp $
31 * $DragonFly: src/games/hack/hack.tty.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $
34 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
35 /* hack.tty.c - version 1.0.3 */
37 * With thanks to the people who sent code for SYSV - hpscdi!jon,
38 * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
41 #include <termios.h>
42 #include "hack.h"
45 * Some systems may have getchar() return EOF for various reasons, and
46 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
47 * FIXME: is this still valid nowadays?
49 #define NR_OF_EOFS 20
51 static char erase_char, kill_char;
52 static boolean settty_needed = FALSE;
53 struct termios inittyb, curttyb;
55 static void setctty(void);
58 * Get initial state of terminal, set ospeed (for termcap routines)
59 * and switch off tab expansion if necessary.
60 * Called by startup() in termcap.c and after returning from ! or ^Z
62 void
63 gettty(void)
65 if (tcgetattr(fileno(stdin), &inittyb) < 0)
66 perror("Hack (gettty)");
67 curttyb = inittyb;
68 erase_char = inittyb.c_cc[VERASE];
69 kill_char = inittyb.c_cc[VKILL];
70 getioctls();
72 /* do not expand tabs - they might be needed inside a cm sequence */
73 if (curttyb.c_oflag & OXTABS) {
74 curttyb.c_oflag &= ~OXTABS;
75 setctty();
77 settty_needed = TRUE;
80 /* reset terminal to original state */
81 void
82 settty(const char *s)
84 clear_screen();
85 end_screen();
86 if (s)
87 printf("%s", s);
88 fflush(stdout);
89 if (tcsetattr(fileno(stdin), TCSANOW, &inittyb) < 0)
90 perror("Hack (settty)");
91 flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
92 flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
93 setioctls();
96 static void
97 setctty(void)
99 if (tcsetattr(fileno(stdin), TCSANOW, &curttyb) < 0)
100 perror("Hack (setctty)");
103 void
104 setftty(void)
106 u_long ef = 0; /* desired value of flags & ECHO */
107 u_long cf = !(ICANON); /* desired value of flags & CBREAK */
108 int change = 0;
110 flags.cbreak = ON;
111 flags.echo = OFF;
112 /* Should use (ECHO|CRMOD) here instead of ECHO */
113 if ((curttyb.c_lflag & ECHO) != ef) {
114 curttyb.c_lflag &= ~ECHO;
115 change++;
117 if ((curttyb.c_lflag & ICANON) != cf) {
118 curttyb.c_lflag &= ~ICANON;
119 curttyb.c_lflag |= cf;
120 /* be satisfied with one character; no timeout */
121 curttyb.c_cc[VMIN] = 1; /* was VEOF */
122 curttyb.c_cc[VTIME] = 0; /* was VEOL */
123 change++;
125 if (change)
126 setctty();
127 start_screen();
130 /* fatal error */
131 /* VARARGS1 */
132 void
133 error(const char *s, ...)
135 va_list ap;
137 if (settty_needed)
138 settty(NULL);
139 va_start(ap, s);
140 vprintf(s, ap);
141 va_end(ap);
142 putchar('\n');
143 exit(1);
147 * Read a line closed with '\n' into the array char bufp[BUFSZ].
148 * (The '\n' is not stored. The string is closed with a '\0'.)
149 * Reading can be interrupted by an escape ('\033') - now the
150 * resulting string is "\033".
152 void
153 getlin(char *bufp)
155 char *obufp = bufp;
156 int c;
158 flags.toplin = 2; /* nonempty, no --More-- required */
159 for (;;) {
160 fflush(stdout);
161 if ((c = getchar()) == EOF) {
162 *bufp = 0;
163 return;
165 if (c == '\033') {
166 *obufp = c;
167 obufp[1] = 0;
168 return;
170 if (c == erase_char || c == '\b') {
171 if (bufp != obufp) {
172 bufp--;
173 putstr("\b \b"); /* putsym converts \b */
174 } else
175 bell();
176 } else if (c == '\n') {
177 *bufp = 0;
178 return;
179 } else if (' ' <= c && c < '\177') {
181 * avoid isprint() - some people don't have it ' ' is
182 * not always a printing char
184 *bufp = c;
185 bufp[1] = 0;
186 putstr(bufp);
187 if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)
188 bufp++;
189 } else if (c == kill_char || c == '\177') { /* Robert Viduya */
190 /* this test last - @ might be the kill_char */
191 while (bufp != obufp) {
192 bufp--;
193 putstr("\b \b");
195 } else
196 bell();
200 void
201 getret(void)
203 cgetret("");
206 void
207 cgetret(const char *s)
209 putsym('\n');
210 if (flags.standout)
211 standoutbeg();
212 putstr("Hit ");
213 putstr(flags.cbreak ? "space" : "return");
214 putstr(" to continue: ");
215 if (flags.standout)
216 standoutend();
217 xwaitforspace(s);
220 char morc; /* tell the outside world what char he used */
222 void
223 xwaitforspace(const char *s) /* chars allowed besides space or return */
225 int c;
227 morc = 0;
228 while ((c = readchar()) != '\n') {
229 if (flags.cbreak) {
230 if (c == ' ')
231 break;
232 if (s && strchr(s, c)) {
233 morc = c;
234 break;
236 bell();
241 char *
242 parse(void)
244 static char inputline[COLNO];
245 int foo;
247 flags.move = 1;
248 if (!Invisible)
249 curs_on_u();
250 else
251 home();
252 while ((foo = readchar()) >= '0' && foo <= '9')
253 multi = 10 * multi + foo - '0';
254 if (multi) {
255 multi--;
256 save_cm = inputline;
258 inputline[0] = foo;
259 inputline[1] = 0;
260 if (foo == 'f' || foo == 'F') {
261 inputline[1] = getchar();
262 #ifdef QUEST
263 if (inputline[1] == foo)
264 inputline[2] = getchar();
265 else
266 #endif /* QUEST */
267 inputline[2] = 0;
269 if (foo == 'm' || foo == 'M') {
270 inputline[1] = getchar();
271 inputline[2] = 0;
273 clrlin();
274 return (inputline);
277 char
278 readchar(void)
280 int sym;
282 fflush(stdout);
283 if ((sym = getchar()) == EOF)
284 #ifdef NR_OF_EOFS
285 { /*
286 * Some SYSV systems seem to return EOFs for various reasons
287 * (?like when one hits break or for interrupted systemcalls?),
288 * and we must see several before we quit.
290 int cnt = NR_OF_EOFS;
291 while (cnt--) {
292 clearerr(stdin); /* omit if clearerr is undefined */
293 if ((sym = getchar()) != EOF)
294 goto noteof;
296 end_of_input();
297 noteof:;
299 #else
300 end_of_input();
301 #endif /* NR_OF_EOFS */
302 if (flags.toplin == 1)
303 flags.toplin = 2;
304 return ((char)sym);
307 void
308 end_of_input(void)
310 settty("End of input?\n");
311 clearlocks();
312 exit(0);