xref: /original-bsd/usr.bin/ex/ex_get.c (revision de38840f)
1 /* Copyright (c) 1981 Regents of the University of California */
2 static char *sccsid = "@(#)ex_get.c	7.1	07/08/81";
3 #include "ex.h"
4 #include "ex_tty.h"
5 
6 /*
7  * Input routines for command mode.
8  * Since we translate the end of reads into the implied ^D's
9  * we have different flavors of routines which do/don't return such.
10  */
11 static	bool junkbs;
12 short	lastc = '\n';
13 
14 ignchar()
15 {
16 	ignore(getchar());
17 }
18 
19 getchar()
20 {
21 	register int c;
22 
23 	do
24 		c = getcd();
25 	while (!globp && c == CTRL(d));
26 	return (c);
27 }
28 
29 getcd()
30 {
31 	register int c;
32 
33 again:
34 	c = getach();
35 	if (c == EOF)
36 		return (c);
37 	c &= TRIM;
38 	if (!inopen)
39 		if (!globp && c == CTRL(d))
40 			setlastchar('\n');
41 		else if (junk(c)) {
42 			checkjunk(c);
43 			goto again;
44 		}
45 	return (c);
46 }
47 
48 peekchar()
49 {
50 
51 	if (peekc == 0)
52 		peekc = getchar();
53 	return (peekc);
54 }
55 
56 peekcd()
57 {
58 	if (peekc == 0)
59 		peekc = getcd();
60 	return (peekc);
61 }
62 
63 getach()
64 {
65 	register int c;
66 	static char inline[128];
67 	struct stat statb;
68 
69 	c = peekc;
70 	if (c != 0) {
71 		peekc = 0;
72 		return (c);
73 	}
74 	if (globp) {
75 		if (*globp)
76 			return (*globp++);
77 		globp = 0;
78 		return (lastc = EOF);
79 	}
80 top:
81 	if (input) {
82 		if (c = *input++) {
83 			if (c &= TRIM)
84 				return (lastc = c);
85 			goto top;
86 		}
87 		input = 0;
88 	}
89 	flush();
90 	if (intty) {
91 		c = read(0, inline, sizeof inline - 4);
92 		if (c < 0)
93 			return (lastc = EOF);
94 		if (c == 0 || inline[c-1] != '\n')
95 			inline[c++] = CTRL(d);
96 		if (inline[c-1] == '\n')
97 			noteinp();
98 		inline[c] = 0;
99 		for (c--; c >= 0; c--)
100 			if (inline[c] == 0)
101 				inline[c] = QUOTE;
102 		input = inline;
103 		goto top;
104 	}
105 /* mjm:	if (read(0, (char *) &lastc, 1) != 1)	CHANGED and added else */
106 	if (read(0, inline, 1) != 1)
107 		lastc = EOF;
108 	else				/* mjm: lastc is a short! */
109 		lastc = inline[0];	/* mjm: in rightmost 8 bits ! */
110 	return (lastc);
111 }
112 
113 /*
114  * Input routine for insert/append/change in command mode.
115  * Most work here is in handling autoindent.
116  */
117 static	short	lastin;
118 
119 gettty()
120 {
121 	register int c = 0;
122 	register char *cp = genbuf;
123 	char hadup = 0;
124 	int numbline();
125 	extern int (*Pline)();
126 	int offset = Pline == numbline ? 8 : 0;
127 	int ch;
128 
129 	if (intty && !inglobal) {
130 		if (offset) {
131 			holdcm = 1;
132 			printf("  %4d  ", lineDOT() + 1);
133 			flush();
134 			holdcm = 0;
135 		}
136 		if (value(AUTOINDENT) ^ aiflag) {
137 			holdcm = 1;
138 #ifdef LISPCODE
139 			if (value(LISP))
140 				lastin = lindent(dot + 1);
141 #endif
142 			tab(lastin + offset);
143 			while ((c = getcd()) == CTRL(d)) {
144 				if (lastin == 0 && isatty(0) == -1) {
145 					holdcm = 0;
146 					return (EOF);
147 				}
148 				lastin = backtab(lastin);
149 				tab(lastin + offset);
150 			}
151 			switch (c) {
152 
153 			case '^':
154 			case '0':
155 				ch = getcd();
156 				if (ch == CTRL(d)) {
157 					if (c == '0')
158 						lastin = 0;
159 					if (!OS) {
160 						putchar('\b' | QUOTE);
161 						putchar(' ' | QUOTE);
162 						putchar('\b' | QUOTE);
163 					}
164 					tab(offset);
165 					hadup = 1;
166 					c = getchar();
167 				} else
168 					ungetchar(ch);
169 				break;
170 
171 			case '.':
172 				if (peekchar() == '\n') {
173 					ignchar();
174 					noteinp();
175 					holdcm = 0;
176 					return (EOF);
177 				}
178 				break;
179 
180 			case '\n':
181 				hadup = 1;
182 				break;
183 			}
184 		}
185 		flush();
186 		holdcm = 0;
187 	}
188 	if (c == 0)
189 		c = getchar();
190 	while (c != EOF && c != '\n') {
191 		if (cp > &genbuf[LBSIZE - 2])
192 			error("Input line too long");
193 		*cp++ = c;
194 		c = getchar();
195 	}
196 	if (c == EOF) {
197 		if (inglobal)
198 			ungetchar(EOF);
199 		return (EOF);
200 	}
201 	*cp = 0;
202 	cp = linebuf;
203 	if ((value(AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
204 		lastin = c = smunch(lastin, genbuf);
205 		for (c = lastin; c >= value(TABSTOP); c -= value(TABSTOP))
206 			*cp++ = '\t';
207 		for (; c > 0; c--)
208 			*cp++ = ' ';
209 	}
210 	CP(cp, genbuf);
211 	if (linebuf[0] == '.' && linebuf[1] == 0)
212 		return (EOF);
213 	return (0);
214 }
215 
216 /*
217  * Crunch the indent.
218  * Hard thing here is that in command mode some of the indent
219  * is only implicit, so we must seed the column counter.
220  * This should really be done differently so as to use the whitecnt routine
221  * and also to hack indenting for LISP.
222  */
223 smunch(col, ocp)
224 	register int col;
225 	char *ocp;
226 {
227 	register char *cp;
228 
229 	cp = ocp;
230 	for (;;)
231 		switch (*cp++) {
232 
233 		case ' ':
234 			col++;
235 			continue;
236 
237 		case '\t':
238 			col += value(TABSTOP) - (col % value(TABSTOP));
239 			continue;
240 
241 		default:
242 			cp--;
243 			CP(ocp, cp);
244 			return (col);
245 		}
246 }
247 
248 char	*cntrlhm =	"^H discarded\n";
249 
250 checkjunk(c)
251 	char c;
252 {
253 
254 	if (junkbs == 0 && c == '\b') {
255 		write(2, cntrlhm, 13);
256 		junkbs = 1;
257 	}
258 }
259 
260 line *
261 setin(addr)
262 	line *addr;
263 {
264 
265 	if (addr == zero)
266 		lastin = 0;
267 	else
268 		getline(*addr), lastin = smunch(0, linebuf);
269 }
270