1 /*
2  * This code contains changes by
3  *      Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4  *
5  * Conditions 1, 2, and 4 and the no-warranty notice below apply
6  * to these changes.
7  *
8  *
9  * Copyright (c) 1980, 1993
10  * 	The Regents of the University of California.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  * 	This product includes software developed by the University of
23  * 	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *
41  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  *   Redistributions of source code and documentation must retain the
47  *    above copyright notice, this list of conditions and the following
48  *    disclaimer.
49  *   Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  *   All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *      This product includes software developed or owned by Caldera
55  *      International, Inc.
56  *   Neither the name of Caldera International, Inc. nor the names of
57  *    other contributors may be used to endorse or promote products
58  *    derived from this software without specific prior written permission.
59  *
60  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64  * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65  * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72  */
73 
74 #ifndef	lint
75 #ifdef	DOSCCS
76 static char sccsid[] = "@(#)ex_get.c	1.17 (gritter) 2/17/05";
77 #endif
78 #endif
79 
80 /* from ex_get.c	7.6 (Berkeley) 6/7/85 */
81 
82 #include "ex.h"
83 #include "ex_tty.h"
84 
85 /*
86  * Input routines for command mode.
87  * Since we translate the end of reads into the implied ^D's
88  * we have different flavors of routines which do/don't return such.
89  */
90 static	bool junkbs;
91 int	lastc = '\n';
92 
93 void
ignchar(void)94 ignchar(void)
95 {
96 	ignore(getchar());
97 }
98 
99 int
getach(void)100 getach(void)
101 {
102 	register int c;
103 	static char in_line[BUFSIZ];
104 	/* struct stat statb; */
105 
106 	c = peekc;
107 	if (c != 0) {
108 		peekc = 0;
109 		return (c);
110 	}
111 	if (globp) {
112 		if (*globp)
113 			return (*globp++&0377);
114 		globp = 0;
115 		return (lastc = EOF);
116 	}
117 top:
118 	if (input) {
119 		if (c = *input++&0377) {
120 			if (verbose && !intty)
121 				write(2, &input[-1], 1);
122 			if (c &= TRIM)
123 				return (lastc = c);
124 			goto top;
125 		}
126 		input = 0;
127 	}
128 	flush();
129 	if (intty) {
130 		c = read(0, in_line, sizeof in_line - 4);
131 		if (c < 0)
132 			return (lastc = EOF);
133 		if (c == 0 || in_line[c-1] != '\n')
134 			in_line[c++] = CTRL('d');
135 		if (in_line[c-1] == '\n')
136 			noteinp();
137 		in_line[c] = 0;
138 		for (c--; c >= 0; c--)
139 			if (in_line[c] == 0)
140 #ifndef	BIT8
141 				in_line[c] = QUOTE;
142 #else
143 				in_line[c] = '\200';
144 #endif
145 		input = in_line;
146 		goto top;
147 	}
148 	c = read(0, in_line, sizeof in_line - 1);
149 	if(c <= 0)
150 		return(lastc = EOF);
151 	in_line[c] = '\0';
152 	input = in_line;
153 	goto top;
154 }
155 
156 int
getchar(void)157 getchar(void)
158 {
159 	register int c;
160 
161 	do
162 		c = getcd();
163 	while (!globp && c == CTRL('d'));
164 	return (c);
165 }
166 
167 void
checkjunk(int c)168 checkjunk(int c)
169 {
170 
171 	if (junkbs == 0 && c == '\b') {
172 		write(2, cntrlhm, 13);
173 		junkbs = 1;
174 	}
175 }
176 
177 int
getcd(void)178 getcd(void)
179 {
180 	register int c;
181 
182 again:
183 	c = getach();
184 	if (c == EOF)
185 		return (c);
186 	c &= TRIM;
187 	if (!inopen)
188 		if (!globp && c == CTRL('d'))
189 			setlastchar('\n');
190 		else if (junk(c)) {
191 			checkjunk(c);
192 			goto again;
193 		}
194 	return (c);
195 }
196 
197 int
peekchar(void)198 peekchar(void)
199 {
200 
201 	if (peekc == 0)
202 		peekc = getchar();
203 	return (peekc);
204 }
205 
206 int
peekcd(void)207 peekcd(void)
208 {
209 	if (peekc == 0)
210 		peekc = getcd();
211 	return (peekc);
212 }
213 
214 /*
215  * Crunch the indent.
216  * Hard thing here is that in command mode some of the indent
217  * is only implicit, so we must seed the column counter.
218  * This should really be done differently so as to use the whitecnt routine
219  * and also to hack indenting for LISP.
220  */
221 int
smunch(register int col,char * ocp)222 smunch(register int col, char *ocp)
223 {
224 	register char *cp;
225 
226 	cp = ocp;
227 	for (;;)
228 		switch (*cp++) {
229 
230 		case ' ':
231 			col++;
232 			continue;
233 
234 		case '\t':
235 			col += value(TABSTOP) - (col % value(TABSTOP));
236 			continue;
237 
238 		default:
239 			cp--;
240 			CP(ocp, cp);
241 			return (col);
242 		}
243 }
244 
245 /*
246  * Input routine for insert/append/change in command mode.
247  * Most work here is in handling autoindent.
248  */
249 static	short	lastin;
250 
251 int
gettty(void)252 gettty(void)
253 {
254 	register int c = 0;
255 	register char *cp = genbuf;
256 	char hadup = 0;
257 	int offset = Pline == numbline ? 8 : 0;
258 	int ch;
259 
260 	if (intty && !inglobal) {
261 		if (offset) {
262 			holdcm = 1;
263 			printf("  %4d  ", lineDOT() + 1);
264 			flush();
265 			holdcm = 0;
266 		}
267 		if (value(AUTOINDENT) ^ aiflag) {
268 			holdcm = 1;
269 #ifdef LISPCODE
270 			if (value(LISP))
271 				lastin = lindent(dot + 1);
272 #endif
273 			tab(lastin + offset);
274 			while ((c = getcd()) == CTRL('d')) {
275 				if (lastin == 0 && isatty(0) == -1) {
276 					holdcm = 0;
277 					return (EOF);
278 				}
279 				lastin = backtab(lastin);
280 				tab(lastin + offset);
281 			}
282 			switch (c) {
283 
284 			case '^':
285 			case '0':
286 				ch = getcd();
287 				if (ch == CTRL('d')) {
288 					if (c == '0')
289 						lastin = 0;
290 					if (!OS) {
291 						putchar('\b' | QUOTE);
292 						putchar(' ' | QUOTE);
293 						putchar('\b' | QUOTE);
294 					}
295 					tab(offset);
296 					hadup = 1;
297 					c = getchar();
298 				} else
299 					ungetchar(ch);
300 				break;
301 
302 			case '.':
303 				if (peekchar() == '\n') {
304 					ignchar();
305 					noteinp();
306 					holdcm = 0;
307 					return (EOF);
308 				}
309 				break;
310 
311 			case '\n':
312 				hadup = 1;
313 				break;
314 			}
315 		}
316 		flush();
317 		holdcm = 0;
318 	}
319 	if (c == 0)
320 		c = getchar();
321 	while (c != EOF && c != '\n') {
322 		if (cp > &genbuf[LBSIZE - 2])
323 			error(catgets(catd, 1, 71, "Input line too long"));
324 		*cp++ = c;
325 		c = getchar();
326 	}
327 	if (c == EOF) {
328 		if (inglobal)
329 			ungetchar(EOF);
330 		return (EOF);
331 	}
332 	*cp = 0;
333 	cp = linebuf;
334 	if ((value(AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
335 		lastin = c = smunch(lastin, genbuf);
336 		for (c = lastin; c >= value(TABSTOP); c -= value(TABSTOP))
337 			*cp++ = '\t';
338 		for (; c > 0; c--)
339 			*cp++ = ' ';
340 	}
341 	CP(cp, genbuf);
342 	if (linebuf[0] == '.' && linebuf[1] == 0)
343 		return (EOF);
344 	return (0);
345 }
346 
347 void
setin(line * addr)348 setin(line *addr)
349 {
350 
351 	if (addr == zero)
352 		lastin = 0;
353 	else
354 		getline(*addr), lastin = smunch(0, linebuf);
355 }
356