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