Commit | Line | Data |
---|---|---|
7ee5bda9 KB |
1 | /* |
2 | * Copyright (c) 1988 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | */ | |
17 | ||
18 | #ifndef lint | |
e87c8732 | 19 | static char sccsid[] = "@(#)hack.tty.c 5.2 (Berkeley) %G%"; |
7ee5bda9 KB |
20 | #endif /* not lint */ |
21 | ||
22 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ | |
23 | /* hack.tty.c - version 1.0.3 */ | |
24 | /* With thanks to the people who sent code for SYSV - hpscdi!jon, | |
25 | arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */ | |
26 | ||
27 | #include "hack.h" | |
28 | #include <stdio.h> | |
29 | ||
30 | /* | |
31 | * The distinctions here are not BSD - rest but rather USG - rest, as | |
32 | * BSD still has the old sgttyb structure, but SYSV has termio. Thus: | |
33 | */ | |
34 | #ifdef BSD | |
35 | #define V7 | |
36 | #else | |
37 | #define USG | |
38 | #endif BSD | |
39 | ||
40 | /* | |
41 | * Some systems may have getchar() return EOF for various reasons, and | |
42 | * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. | |
43 | */ | |
44 | #ifndef BSD | |
45 | #define NR_OF_EOFS 20 | |
46 | #endif BSD | |
47 | ||
48 | ||
49 | #ifdef USG | |
50 | ||
51 | #include <termio.h> | |
52 | #define termstruct termio | |
53 | #define kill_sym c_cc[VKILL] | |
54 | #define erase_sym c_cc[VERASE] | |
55 | #define EXTABS TAB3 | |
56 | #define tabflgs c_oflag | |
57 | #define echoflgs c_lflag | |
58 | #define cbrkflgs c_lflag | |
59 | #define CBRKMASK ICANON | |
60 | #define CBRKON ! /* reverse condition */ | |
61 | #define OSPEED(x) ((x).c_cflag & CBAUD) | |
62 | #define GTTY(x) (ioctl(0, TCGETA, x)) | |
63 | #define STTY(x) (ioctl(0, TCSETA, x)) /* TCSETAF? TCSETAW? */ | |
64 | ||
65 | #else /* V7 */ | |
66 | ||
67 | #include <sgtty.h> | |
68 | #define termstruct sgttyb | |
69 | #define kill_sym sg_kill | |
70 | #define erase_sym sg_erase | |
71 | #define EXTABS XTABS | |
72 | #define tabflgs sg_flags | |
73 | #define echoflgs sg_flags | |
74 | #define cbrkflgs sg_flags | |
75 | #define CBRKMASK CBREAK | |
76 | #define CBRKON /* empty */ | |
77 | #define OSPEED(x) (x).sg_ospeed | |
78 | #define GTTY(x) (gtty(0, x)) | |
79 | #define STTY(x) (stty(0, x)) | |
80 | ||
81 | #endif USG | |
82 | ||
83 | extern short ospeed; | |
84 | static char erase_char, kill_char; | |
85 | static boolean settty_needed = FALSE; | |
86 | struct termstruct inittyb, curttyb; | |
87 | ||
88 | /* | |
89 | * Get initial state of terminal, set ospeed (for termcap routines) | |
90 | * and switch off tab expansion if necessary. | |
91 | * Called by startup() in termcap.c and after returning from ! or ^Z | |
92 | */ | |
93 | gettty(){ | |
94 | if(GTTY(&inittyb) < 0) | |
95 | perror("Hack (gettty)"); | |
96 | curttyb = inittyb; | |
97 | ospeed = OSPEED(inittyb); | |
98 | erase_char = inittyb.erase_sym; | |
99 | kill_char = inittyb.kill_sym; | |
100 | getioctls(); | |
101 | ||
102 | /* do not expand tabs - they might be needed inside a cm sequence */ | |
103 | if(curttyb.tabflgs & EXTABS) { | |
104 | curttyb.tabflgs &= ~EXTABS; | |
105 | setctty(); | |
106 | } | |
107 | settty_needed = TRUE; | |
108 | } | |
109 | ||
110 | /* reset terminal to original state */ | |
111 | settty(s) char *s; { | |
112 | clear_screen(); | |
113 | end_screen(); | |
114 | if(s) printf(s); | |
115 | (void) fflush(stdout); | |
116 | if(STTY(&inittyb) < 0) | |
117 | perror("Hack (settty)"); | |
118 | flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF; | |
119 | flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF; | |
120 | setioctls(); | |
121 | } | |
122 | ||
123 | setctty(){ | |
124 | if(STTY(&curttyb) < 0) | |
125 | perror("Hack (setctty)"); | |
126 | } | |
127 | ||
128 | ||
129 | setftty(){ | |
130 | register int ef = 0; /* desired value of flags & ECHO */ | |
131 | register int cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */ | |
132 | register int change = 0; | |
133 | flags.cbreak = ON; | |
134 | flags.echo = OFF; | |
135 | /* Should use (ECHO|CRMOD) here instead of ECHO */ | |
136 | if((curttyb.echoflgs & ECHO) != ef){ | |
137 | curttyb.echoflgs &= ~ECHO; | |
138 | /* curttyb.echoflgs |= ef; */ | |
139 | change++; | |
140 | } | |
141 | if((curttyb.cbrkflgs & CBRKMASK) != cf){ | |
142 | curttyb.cbrkflgs &= ~CBRKMASK; | |
143 | curttyb.cbrkflgs |= cf; | |
144 | #ifdef USG | |
145 | /* be satisfied with one character; no timeout */ | |
146 | curttyb.c_cc[VMIN] = 1; /* was VEOF */ | |
147 | curttyb.c_cc[VTIME] = 0; /* was VEOL */ | |
148 | #endif USG | |
149 | change++; | |
150 | } | |
151 | if(change){ | |
152 | setctty(); | |
153 | } | |
154 | start_screen(); | |
155 | } | |
156 | ||
157 | ||
158 | /* fatal error */ | |
159 | /*VARARGS1*/ | |
160 | error(s,x,y) char *s; { | |
161 | if(settty_needed) | |
162 | settty((char *) 0); | |
163 | printf(s,x,y); | |
164 | putchar('\n'); | |
165 | exit(1); | |
166 | } | |
167 | ||
168 | /* | |
169 | * Read a line closed with '\n' into the array char bufp[BUFSZ]. | |
170 | * (The '\n' is not stored. The string is closed with a '\0'.) | |
171 | * Reading can be interrupted by an escape ('\033') - now the | |
172 | * resulting string is "\033". | |
173 | */ | |
174 | getlin(bufp) | |
175 | register char *bufp; | |
176 | { | |
177 | register char *obufp = bufp; | |
178 | register int c; | |
179 | ||
180 | flags.toplin = 2; /* nonempty, no --More-- required */ | |
181 | for(;;) { | |
182 | (void) fflush(stdout); | |
183 | if((c = getchar()) == EOF) { | |
184 | *bufp = 0; | |
185 | return; | |
186 | } | |
187 | if(c == '\033') { | |
188 | *obufp = c; | |
189 | obufp[1] = 0; | |
190 | return; | |
191 | } | |
192 | if(c == erase_char || c == '\b') { | |
193 | if(bufp != obufp) { | |
194 | bufp--; | |
195 | putstr("\b \b"); /* putsym converts \b */ | |
196 | } else bell(); | |
197 | } else if(c == '\n') { | |
198 | *bufp = 0; | |
199 | return; | |
200 | } else if(' ' <= c && c < '\177') { | |
201 | /* avoid isprint() - some people don't have it | |
202 | ' ' is not always a printing char */ | |
203 | *bufp = c; | |
204 | bufp[1] = 0; | |
205 | putstr(bufp); | |
206 | if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) | |
207 | bufp++; | |
208 | } else if(c == kill_char || c == '\177') { /* Robert Viduya */ | |
209 | /* this test last - @ might be the kill_char */ | |
210 | while(bufp != obufp) { | |
211 | bufp--; | |
212 | putstr("\b \b"); | |
213 | } | |
214 | } else | |
215 | bell(); | |
216 | } | |
217 | } | |
218 | ||
219 | getret() { | |
220 | cgetret(""); | |
221 | } | |
222 | ||
223 | cgetret(s) | |
224 | register char *s; | |
225 | { | |
226 | putsym('\n'); | |
227 | if(flags.standout) | |
228 | standoutbeg(); | |
229 | putstr("Hit "); | |
230 | putstr(flags.cbreak ? "space" : "return"); | |
231 | putstr(" to continue: "); | |
232 | if(flags.standout) | |
233 | standoutend(); | |
234 | xwaitforspace(s); | |
235 | } | |
236 | ||
237 | char morc; /* tell the outside world what char he used */ | |
238 | ||
239 | xwaitforspace(s) | |
240 | register char *s; /* chars allowed besides space or return */ | |
241 | { | |
242 | register int c; | |
243 | ||
244 | morc = 0; | |
245 | ||
246 | while((c = readchar()) != '\n') { | |
247 | if(flags.cbreak) { | |
248 | if(c == ' ') break; | |
249 | if(s && index(s,c)) { | |
250 | morc = c; | |
251 | break; | |
252 | } | |
253 | bell(); | |
254 | } | |
255 | } | |
256 | } | |
257 | ||
258 | char * | |
259 | parse() | |
260 | { | |
e87c8732 | 261 | static char inputline[COLNO]; |
7ee5bda9 KB |
262 | register foo; |
263 | ||
264 | flags.move = 1; | |
265 | if(!Invisible) curs_on_u(); else home(); | |
266 | while((foo = readchar()) >= '0' && foo <= '9') | |
267 | multi = 10*multi+foo-'0'; | |
268 | if(multi) { | |
269 | multi--; | |
e87c8732 | 270 | save_cm = inputline; |
7ee5bda9 | 271 | } |
e87c8732 KB |
272 | inputline[0] = foo; |
273 | inputline[1] = 0; | |
7ee5bda9 | 274 | if(foo == 'f' || foo == 'F'){ |
e87c8732 | 275 | inputline[1] = getchar(); |
7ee5bda9 | 276 | #ifdef QUEST |
e87c8732 | 277 | if(inputline[1] == foo) inputline[2] = getchar(); else |
7ee5bda9 | 278 | #endif QUEST |
e87c8732 | 279 | inputline[2] = 0; |
7ee5bda9 KB |
280 | } |
281 | if(foo == 'm' || foo == 'M'){ | |
e87c8732 KB |
282 | inputline[1] = getchar(); |
283 | inputline[2] = 0; | |
7ee5bda9 KB |
284 | } |
285 | clrlin(); | |
e87c8732 | 286 | return(inputline); |
7ee5bda9 KB |
287 | } |
288 | ||
289 | char | |
290 | readchar() { | |
291 | register int sym; | |
292 | ||
293 | (void) fflush(stdout); | |
294 | if((sym = getchar()) == EOF) | |
295 | #ifdef NR_OF_EOFS | |
296 | { /* | |
297 | * Some SYSV systems seem to return EOFs for various reasons | |
298 | * (?like when one hits break or for interrupted systemcalls?), | |
299 | * and we must see several before we quit. | |
300 | */ | |
301 | register int cnt = NR_OF_EOFS; | |
302 | while (cnt--) { | |
303 | clearerr(stdin); /* omit if clearerr is undefined */ | |
304 | if((sym = getchar()) != EOF) goto noteof; | |
305 | } | |
306 | end_of_input(); | |
307 | noteof: ; | |
308 | } | |
309 | #else | |
310 | end_of_input(); | |
311 | #endif NR_OF_EOFS | |
312 | if(flags.toplin == 1) | |
313 | flags.toplin = 2; | |
314 | return((char) sym); | |
315 | } | |
316 | ||
317 | end_of_input() | |
318 | { | |
319 | settty("End of input?\n"); | |
320 | clearlocks(); | |
321 | exit(0); | |
322 | } |