Generally use NULL instead of explicitly casting 0 to some pointer type (part2).
[dragonfly.git] / games / hack / hack.tty.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
1de703da
MD
32 *
33 * @(#)hack.tty.c 8.1 (Berkeley) 5/31/93
34 * $FreeBSD: src/games/hack/hack.tty.c,v 1.6.2.1 2000/07/20 10:35:07 kris Exp $
c7106d58 35 * $DragonFly: src/games/hack/hack.tty.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $
984263bc
MD
36 */
37
984263bc
MD
38/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
39/* hack.tty.c - version 1.0.3 */
40/* With thanks to the people who sent code for SYSV - hpscdi!jon,
41 arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
42
43#include "hack.h"
984263bc
MD
44
45/*
46 * The distinctions here are not BSD - rest but rather USG - rest, as
47 * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
48 */
49#ifdef BSD
50#define V7
51#else
52#define USG
304d60d9 53#endif /* BSD */
984263bc
MD
54
55/*
56 * Some systems may have getchar() return EOF for various reasons, and
57 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
58 */
59#ifndef BSD
60#define NR_OF_EOFS 20
304d60d9 61#endif /* BSD */
984263bc
MD
62
63
64#ifdef USG
65
66#include <termio.h>
67#define termstruct termio
68#define kill_sym c_cc[VKILL]
69#define erase_sym c_cc[VERASE]
70#define EXTABS TAB3
71#define tabflgs c_oflag
72#define echoflgs c_lflag
73#define cbrkflgs c_lflag
74#define CBRKMASK ICANON
75#define CBRKON ! /* reverse condition */
76#define OSPEED(x) ((x).c_cflag & CBAUD)
77#define GTTY(x) (ioctl(0, TCGETA, x))
78#define STTY(x) (ioctl(0, TCSETA, x)) /* TCSETAF? TCSETAW? */
79
80#else /* V7 */
81
82#include <sgtty.h>
83#define termstruct sgttyb
84#define kill_sym sg_kill
85#define erase_sym sg_erase
86#define EXTABS XTABS
87#define tabflgs sg_flags
88#define echoflgs sg_flags
89#define cbrkflgs sg_flags
90#define CBRKMASK CBREAK
91#define CBRKON /* empty */
92#define OSPEED(x) (x).sg_ospeed
c7106d58
PA
93#define GTTY(x) (ioctl(0, TIOCGETP, x))
94#define STTY(x) (ioctl(0, TIOCSETP, x))
984263bc 95
304d60d9 96#endif /* USG */
984263bc 97
984263bc
MD
98static char erase_char, kill_char;
99static boolean settty_needed = FALSE;
100struct termstruct inittyb, curttyb;
101
c7106d58
PA
102static void setctty(void);
103
984263bc
MD
104/*
105 * Get initial state of terminal, set ospeed (for termcap routines)
106 * and switch off tab expansion if necessary.
107 * Called by startup() in termcap.c and after returning from ! or ^Z
108 */
c7106d58
PA
109void
110gettty(void)
111{
984263bc
MD
112 if(GTTY(&inittyb) < 0)
113 perror("Hack (gettty)");
114 curttyb = inittyb;
984263bc
MD
115 erase_char = inittyb.erase_sym;
116 kill_char = inittyb.kill_sym;
117 getioctls();
118
119 /* do not expand tabs - they might be needed inside a cm sequence */
120 if(curttyb.tabflgs & EXTABS) {
121 curttyb.tabflgs &= ~EXTABS;
122 setctty();
123 }
124 settty_needed = TRUE;
125}
126
127/* reset terminal to original state */
c7106d58
PA
128void
129settty(const char *s)
130{
984263bc
MD
131 clear_screen();
132 end_screen();
133 if(s) printf("%s", s);
c7106d58 134 fflush(stdout);
984263bc
MD
135 if(STTY(&inittyb) < 0)
136 perror("Hack (settty)");
137 flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
138 flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
139 setioctls();
140}
141
c7106d58
PA
142static void
143setctty(void)
144{
984263bc
MD
145 if(STTY(&curttyb) < 0)
146 perror("Hack (setctty)");
147}
148
c7106d58
PA
149void
150setftty(void)
151{
984263bc
MD
152int ef = 0; /* desired value of flags & ECHO */
153int cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */
154int change = 0;
155 flags.cbreak = ON;
156 flags.echo = OFF;
157 /* Should use (ECHO|CRMOD) here instead of ECHO */
158 if((curttyb.echoflgs & ECHO) != ef){
159 curttyb.echoflgs &= ~ECHO;
984263bc
MD
160 change++;
161 }
162 if((curttyb.cbrkflgs & CBRKMASK) != cf){
163 curttyb.cbrkflgs &= ~CBRKMASK;
164 curttyb.cbrkflgs |= cf;
165#ifdef USG
166 /* be satisfied with one character; no timeout */
167 curttyb.c_cc[VMIN] = 1; /* was VEOF */
168 curttyb.c_cc[VTIME] = 0; /* was VEOL */
304d60d9 169#endif /* USG */
984263bc
MD
170 change++;
171 }
172 if(change){
173 setctty();
174 }
175 start_screen();
176}
177
178
179/* fatal error */
180/*VARARGS1*/
c7106d58
PA
181void
182error(const char *s, ...)
183{
184 va_list ap;
984263bc 185 if(settty_needed)
902ec341 186 settty(NULL);
c7106d58
PA
187 va_start(ap, s);
188 vprintf(s, ap);
189 va_end(ap);
984263bc
MD
190 putchar('\n');
191 exit(1);
192}
193
194/*
195 * Read a line closed with '\n' into the array char bufp[BUFSZ].
196 * (The '\n' is not stored. The string is closed with a '\0'.)
197 * Reading can be interrupted by an escape ('\033') - now the
198 * resulting string is "\033".
199 */
c7106d58
PA
200void
201getlin(char *bufp)
984263bc
MD
202{
203 char *obufp = bufp;
204 int c;
205
206 flags.toplin = 2; /* nonempty, no --More-- required */
207 for(;;) {
c7106d58 208 fflush(stdout);
984263bc
MD
209 if((c = getchar()) == EOF) {
210 *bufp = 0;
211 return;
212 }
213 if(c == '\033') {
214 *obufp = c;
215 obufp[1] = 0;
216 return;
217 }
218 if(c == erase_char || c == '\b') {
219 if(bufp != obufp) {
220 bufp--;
221 putstr("\b \b"); /* putsym converts \b */
222 } else bell();
223 } else if(c == '\n') {
224 *bufp = 0;
225 return;
226 } else if(' ' <= c && c < '\177') {
227 /* avoid isprint() - some people don't have it
228 ' ' is not always a printing char */
229 *bufp = c;
230 bufp[1] = 0;
231 putstr(bufp);
232 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
233 bufp++;
234 } else if(c == kill_char || c == '\177') { /* Robert Viduya */
235 /* this test last - @ might be the kill_char */
236 while(bufp != obufp) {
237 bufp--;
238 putstr("\b \b");
239 }
240 } else
241 bell();
242 }
243}
244
c7106d58
PA
245void
246getret(void)
247{
984263bc
MD
248 cgetret("");
249}
250
c7106d58
PA
251void
252cgetret(const char *s)
984263bc
MD
253{
254 putsym('\n');
255 if(flags.standout)
256 standoutbeg();
257 putstr("Hit ");
258 putstr(flags.cbreak ? "space" : "return");
259 putstr(" to continue: ");
260 if(flags.standout)
261 standoutend();
262 xwaitforspace(s);
263}
264
265char morc; /* tell the outside world what char he used */
266
c7106d58
PA
267void
268xwaitforspace(const char *s) /* chars allowed besides space or return */
984263bc
MD
269{
270int c;
271
272 morc = 0;
273
274 while((c = readchar()) != '\n') {
275 if(flags.cbreak) {
276 if(c == ' ') break;
277 if(s && index(s,c)) {
278 morc = c;
279 break;
280 }
281 bell();
282 }
283 }
284}
285
286char *
c7106d58 287parse(void)
984263bc
MD
288{
289 static char inputline[COLNO];
290 int foo;
291
292 flags.move = 1;
293 if(!Invisible) curs_on_u(); else home();
294 while((foo = readchar()) >= '0' && foo <= '9')
295 multi = 10*multi+foo-'0';
296 if(multi) {
297 multi--;
298 save_cm = inputline;
299 }
300 inputline[0] = foo;
301 inputline[1] = 0;
302 if(foo == 'f' || foo == 'F'){
303 inputline[1] = getchar();
304#ifdef QUEST
305 if(inputline[1] == foo) inputline[2] = getchar(); else
304d60d9 306#endif /* QUEST */
984263bc
MD
307 inputline[2] = 0;
308 }
309 if(foo == 'm' || foo == 'M'){
310 inputline[1] = getchar();
311 inputline[2] = 0;
312 }
313 clrlin();
314 return(inputline);
315}
316
317char
c7106d58
PA
318readchar(void)
319{
984263bc
MD
320 int sym;
321
c7106d58 322 fflush(stdout);
984263bc
MD
323 if((sym = getchar()) == EOF)
324#ifdef NR_OF_EOFS
325 { /*
326 * Some SYSV systems seem to return EOFs for various reasons
327 * (?like when one hits break or for interrupted systemcalls?),
328 * and we must see several before we quit.
329 */
330 int cnt = NR_OF_EOFS;
331 while (cnt--) {
332 clearerr(stdin); /* omit if clearerr is undefined */
333 if((sym = getchar()) != EOF) goto noteof;
334 }
335 end_of_input();
336 noteof: ;
337 }
338#else
339 end_of_input();
304d60d9 340#endif /* NR_OF_EOFS */
984263bc
MD
341 if(flags.toplin == 1)
342 flags.toplin = 2;
343 return((char) sym);
344}
345
c7106d58
PA
346void
347end_of_input(void)
984263bc
MD
348{
349 settty("End of input?\n");
350 clearlocks();
351 exit(0);
352}