]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/hack/hack.tty.c
This commit was generated by cvs2svn to compensate for changes in r43148,
[FreeBSD/FreeBSD.git] / games / hack / hack.tty.c
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.
32  */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)hack.tty.c  8.1 (Berkeley) 5/31/93";
36 #endif /* not lint */
37
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"
44 #include        <stdio.h>
45
46 /*
47  * The distinctions here are not BSD - rest but rather USG - rest, as
48  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
49  */
50 #ifdef BSD
51 #define V7
52 #else
53 #define USG
54 #endif BSD
55
56 /*
57  * Some systems may have getchar() return EOF for various reasons, and
58  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
59  */
60 #ifndef BSD
61 #define NR_OF_EOFS      20
62 #endif BSD
63
64
65 #ifdef USG
66
67 #include        <termio.h>
68 #define termstruct      termio
69 #define kill_sym        c_cc[VKILL]
70 #define erase_sym       c_cc[VERASE]
71 #define EXTABS          TAB3
72 #define tabflgs         c_oflag
73 #define echoflgs        c_lflag
74 #define cbrkflgs        c_lflag
75 #define CBRKMASK        ICANON
76 #define CBRKON          ! /* reverse condition */
77 #define OSPEED(x)       ((x).c_cflag & CBAUD)
78 #define GTTY(x)         (ioctl(0, TCGETA, x))
79 #define STTY(x)         (ioctl(0, TCSETA, x))   /* TCSETAF? TCSETAW? */
80
81 #else   /* V7 */
82
83 #include        <sgtty.h>
84 #define termstruct      sgttyb
85 #define kill_sym        sg_kill
86 #define erase_sym       sg_erase
87 #define EXTABS          XTABS
88 #define tabflgs         sg_flags
89 #define echoflgs        sg_flags
90 #define cbrkflgs        sg_flags
91 #define CBRKMASK        CBREAK
92 #define CBRKON          /* empty */
93 #define OSPEED(x)       (x).sg_ospeed
94 #define GTTY(x)         (gtty(0, x))
95 #define STTY(x)         (stty(0, x))
96
97 #endif USG
98
99 extern short ospeed;
100 static char erase_char, kill_char;
101 static boolean settty_needed = FALSE;
102 struct termstruct inittyb, curttyb;
103
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  */
109 gettty(){
110         if(GTTY(&inittyb) < 0)
111                 perror("Hack (gettty)");
112         curttyb = inittyb;
113         ospeed = OSPEED(inittyb);
114         erase_char = inittyb.erase_sym;
115         kill_char = inittyb.kill_sym;
116         getioctls();
117
118         /* do not expand tabs - they might be needed inside a cm sequence */
119         if(curttyb.tabflgs & EXTABS) {
120                 curttyb.tabflgs &= ~EXTABS;
121                 setctty();
122         }
123         settty_needed = TRUE;
124 }
125
126 /* reset terminal to original state */
127 settty(s) char *s; {
128         clear_screen();
129         end_screen();
130         if(s) printf(s);
131         (void) fflush(stdout);
132         if(STTY(&inittyb) < 0)
133                 perror("Hack (settty)");
134         flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
135         flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
136         setioctls();
137 }
138
139 setctty(){
140         if(STTY(&curttyb) < 0)
141                 perror("Hack (setctty)");
142 }
143
144
145 setftty(){
146 register int ef = 0;                    /* desired value of flags & ECHO */
147 register int cf = CBRKON(CBRKMASK);     /* desired value of flags & CBREAK */
148 register int change = 0;
149         flags.cbreak = ON;
150         flags.echo = OFF;
151         /* Should use (ECHO|CRMOD) here instead of ECHO */
152         if((curttyb.echoflgs & ECHO) != ef){
153                 curttyb.echoflgs &= ~ECHO;
154 /*              curttyb.echoflgs |= ef;                                 */
155                 change++;
156         }
157         if((curttyb.cbrkflgs & CBRKMASK) != cf){
158                 curttyb.cbrkflgs &= ~CBRKMASK;
159                 curttyb.cbrkflgs |= cf;
160 #ifdef USG
161                 /* be satisfied with one character; no timeout */
162                 curttyb.c_cc[VMIN] = 1;         /* was VEOF */
163                 curttyb.c_cc[VTIME] = 0;        /* was VEOL */
164 #endif USG
165                 change++;
166         }
167         if(change){
168                 setctty();
169         }
170         start_screen();
171 }
172
173
174 /* fatal error */
175 /*VARARGS1*/
176 error(s,x,y) char *s; {
177         if(settty_needed)
178                 settty((char *) 0);
179         printf(s,x,y);
180         putchar('\n');
181         exit(1);
182 }
183
184 /*
185  * Read a line closed with '\n' into the array char bufp[BUFSZ].
186  * (The '\n' is not stored. The string is closed with a '\0'.)
187  * Reading can be interrupted by an escape ('\033') - now the
188  * resulting string is "\033".
189  */
190 getlin(bufp)
191 register char *bufp;
192 {
193         register char *obufp = bufp;
194         register int c;
195
196         flags.toplin = 2;               /* nonempty, no --More-- required */
197         for(;;) {
198                 (void) fflush(stdout);
199                 if((c = getchar()) == EOF) {
200                         *bufp = 0;
201                         return;
202                 }
203                 if(c == '\033') {
204                         *obufp = c;
205                         obufp[1] = 0;
206                         return;
207                 }
208                 if(c == erase_char || c == '\b') {
209                         if(bufp != obufp) {
210                                 bufp--;
211                                 putstr("\b \b"); /* putsym converts \b */
212                         } else  bell();
213                 } else if(c == '\n') {
214                         *bufp = 0;
215                         return;
216                 } else if(' ' <= c && c < '\177') {
217                                 /* avoid isprint() - some people don't have it
218                                    ' ' is not always a printing char */
219                         *bufp = c;
220                         bufp[1] = 0;
221                         putstr(bufp);
222                         if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
223                                 bufp++;
224                 } else if(c == kill_char || c == '\177') { /* Robert Viduya */
225                                 /* this test last - @ might be the kill_char */
226                         while(bufp != obufp) {
227                                 bufp--;
228                                 putstr("\b \b");
229                         }
230                 } else
231                         bell();
232         }
233 }
234
235 getret() {
236         cgetret("");
237 }
238
239 cgetret(s)
240 register char *s;
241 {
242         putsym('\n');
243         if(flags.standout)
244                 standoutbeg();
245         putstr("Hit ");
246         putstr(flags.cbreak ? "space" : "return");
247         putstr(" to continue: ");
248         if(flags.standout)
249                 standoutend();
250         xwaitforspace(s);
251 }
252
253 char morc;      /* tell the outside world what char he used */
254
255 xwaitforspace(s)
256 register char *s;       /* chars allowed besides space or return */
257 {
258 register int c;
259
260         morc = 0;
261
262         while((c = readchar()) != '\n') {
263             if(flags.cbreak) {
264                 if(c == ' ') break;
265                 if(s && index(s,c)) {
266                         morc = c;
267                         break;
268                 }
269                 bell();
270             }
271         }
272 }
273
274 char *
275 parse()
276 {
277         static char inputline[COLNO];
278         register foo;
279
280         flags.move = 1;
281         if(!Invisible) curs_on_u(); else home();
282         while((foo = readchar()) >= '0' && foo <= '9')
283                 multi = 10*multi+foo-'0';
284         if(multi) {
285                 multi--;
286                 save_cm = inputline;
287         }
288         inputline[0] = foo;
289         inputline[1] = 0;
290         if(foo == 'f' || foo == 'F'){
291                 inputline[1] = getchar();
292 #ifdef QUEST
293                 if(inputline[1] == foo) inputline[2] = getchar(); else
294 #endif QUEST
295                 inputline[2] = 0;
296         }
297         if(foo == 'm' || foo == 'M'){
298                 inputline[1] = getchar();
299                 inputline[2] = 0;
300         }
301         clrlin();
302         return(inputline);
303 }
304
305 char
306 readchar() {
307         register int sym;
308
309         (void) fflush(stdout);
310         if((sym = getchar()) == EOF)
311 #ifdef NR_OF_EOFS
312         { /*
313            * Some SYSV systems seem to return EOFs for various reasons
314            * (?like when one hits break or for interrupted systemcalls?),
315            * and we must see several before we quit.
316            */
317                 register int cnt = NR_OF_EOFS;
318                 while (cnt--) {
319                     clearerr(stdin);    /* omit if clearerr is undefined */
320                     if((sym = getchar()) != EOF) goto noteof;
321                 }
322                 end_of_input();
323              noteof:    ;
324         }
325 #else
326                 end_of_input();
327 #endif NR_OF_EOFS
328         if(flags.toplin == 1)
329                 flags.toplin = 2;
330         return((char) sym);
331 }
332
333 end_of_input()
334 {
335         settty("End of input?\n");
336         clearlocks();
337         exit(0);
338 }