xref: /titanic_52/usr/src/cmd/vi/port/ex_get.c (revision 84ab085a13f931bc78e7415e7ce921dbaa14fcb3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /* Copyright (c) 1981 Regents of the University of California */
27 
28 /*
29  * Copyright (c) 2001 by Sun Microsystems, Inc.
30  * All rights reserved.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.10	*/
34 
35 #include "ex.h"
36 #include "ex_tty.h"
37 
38 /*
39  * Input routines for command mode.
40  * Since we translate the end of reads into the implied ^D's
41  * we have different flavors of routines which do/don't return such.
42  */
43 static	bool junkbs;
44 short	lastc = '\n';
45 
46 ignchar()
47 {
48 	(void)getchar();
49 }
50 
51 getchar()
52 {
53 	register int c;
54 
55 	do
56 		c = getcd();
57 	while (!globp && c == CTRL('d'));
58 	return (c);
59 }
60 
61 getcd()
62 {
63 	register int c;
64 	extern short slevel;
65 
66 again:
67 	c = getach();
68 	if (c == EOF)
69 		return (c);
70 	if (!inopen && slevel==0)
71 		if (!globp && c == CTRL('d'))
72 			setlastchar('\n');
73 		else if (junk(c)) {
74 			checkjunk(c);
75 			goto again;
76 		}
77 	return (c);
78 }
79 
80 peekchar()
81 {
82 
83 	if (peekc == 0)
84 		peekc = getchar();
85 	return (peekc);
86 }
87 
88 peekcd()
89 {
90 	if (peekc == 0)
91 		peekc = getcd();
92 	return (peekc);
93 }
94 
95 int verbose;
96 getach()
97 {
98 	register int c, i, prev;
99 	static unsigned char inputline[128];
100 
101 	c = peekc;
102 	if (c != 0) {
103 		peekc = 0;
104 		return (c);
105 	}
106 	if (globp) {
107 		if (*globp)
108 			return (*globp++);
109 		globp = 0;
110 		return (lastc = EOF);
111 	}
112 top:
113 	if (input) {
114 		if(c = *input++)
115 			return (lastc = c);
116 		input = 0;
117 	}
118 	flush();
119 	if (intty) {
120 		c = read(0, inputline, sizeof inputline - 4);
121 		if (c < 0)
122 			return (lastc = EOF);
123 		if (c == 0 || inputline[c-1] != '\n')
124 			inputline[c++] = CTRL('d');
125 		if (inputline[c-1] == '\n')
126 			noteinp();
127 		prev = 0;
128 		/* remove nulls from input buffer */
129 		for (i = 0; i < c; i++)
130 			if(inputline[i] != 0)
131 				inputline[prev++] = inputline[i];
132 		inputline[prev] = 0;
133 		input = inputline;
134 		goto top;
135 	}
136 	if (read(0, inputline, 1) != 1)
137 		lastc = EOF;
138 	else {
139 		lastc = inputline[0];
140 		if (verbose)
141 			write(2, inputline, 1);
142 	}
143 	return (lastc);
144 }
145 
146 /*
147  * Input routine for insert/append/change in command mode.
148  * Most work here is in handling autoindent.
149  */
150 static	short	lastin;
151 
152 gettty()
153 {
154 	register int c = 0;
155 	register unsigned char *cp = genbuf;
156 	unsigned char hadup = 0;
157 	int numbline();
158 	extern int (*Pline)();
159 	int offset = Pline == numbline ? 8 : 0;
160 	int ch;
161 
162 	if (intty && !inglobal) {
163 		if (offset) {
164 			holdcm = 1;
165 			printf("  %4d  ", lineDOT() + 1);
166 			flush();
167 			holdcm = 0;
168 		}
169 		if (value(vi_AUTOINDENT) ^ aiflag) {
170 			holdcm = 1;
171 			if (value(vi_LISP))
172 				lastin = lindent(dot + 1);
173 			gotab(lastin + offset);
174 			while ((c = getcd()) == CTRL('d')) {
175 				if (lastin == 0 && isatty(0) == -1) {
176 					holdcm = 0;
177 					return (EOF);
178 				}
179 				lastin = backtab(lastin);
180 				gotab(lastin + offset);
181 			}
182 			switch (c) {
183 
184 			case '^':
185 			case '0':
186 				ch = getcd();
187 				if (ch == CTRL('d')) {
188 					if (c == '0')
189 						lastin = 0;
190 					if (!over_strike) {
191 						putchar((int)('\b' | QUOTE));
192 						putchar((int)(' ' | QUOTE));
193 						putchar((int)('\b' | QUOTE));
194 					}
195 					gotab(offset);
196 					hadup = 1;
197 					c = getchar();
198 				} else
199 					ungetchar(ch);
200 				break;
201 
202 			case '.':
203 				if (peekchar() == '\n') {
204 					ignchar();
205 					noteinp();
206 					holdcm = 0;
207 					return (EOF);
208 				}
209 				break;
210 
211 			case '\n':
212 				hadup = 1;
213 				break;
214 			}
215 		}
216 		flush();
217 		holdcm = 0;
218 	}
219 	if (c == 0)
220 		c = getchar();
221 	while (c != EOF && c != '\n') {
222 		if (cp > &genbuf[LBSIZE - 2])
223 			error(gettext("Input line too long"));
224 		*cp++ = c;
225 		c = getchar();
226 	}
227 	if (c == EOF) {
228 		if (inglobal)
229 			ungetchar(EOF);
230 		return (EOF);
231 	}
232 	*cp = 0;
233 	cp = linebuf;
234 	if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
235 		lastin = c = smunch(lastin, genbuf);
236 		for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP))
237 			*cp++ = '\t';
238 		for (; c > 0; c--)
239 			*cp++ = ' ';
240 	}
241 	CP(cp, genbuf);
242 	if (linebuf[0] == '.' && linebuf[1] == 0)
243 		return (EOF);
244 	return (0);
245 }
246 
247 /*
248  * Crunch the indent.
249  * Hard thing here is that in command mode some of the indent
250  * is only implicit, so we must seed the column counter.
251  * This should really be done differently so as to use the whitecnt routine
252  * and also to hack indenting for LISP.
253  */
254 smunch(col, ocp)
255 	register int col;
256 	unsigned char *ocp;
257 {
258 	register unsigned char *cp;
259 
260 	cp = ocp;
261 	for (;;)
262 		switch (*cp++) {
263 
264 		case ' ':
265 			col++;
266 			continue;
267 
268 		case '\t':
269 			col += value(vi_TABSTOP) - (col % value(vi_TABSTOP));
270 			continue;
271 
272 		default:
273 			cp--;
274 			CP(ocp, cp);
275 			return (col);
276 		}
277 }
278 
279 unsigned char	*cntrlhm =	(unsigned char *)"^H discarded\n";
280 
281 checkjunk(c)
282 	unsigned char c;
283 {
284 
285 	if (junkbs == 0 && c == '\b') {
286 		write(2, cntrlhm, 13);
287 		junkbs = 1;
288 	}
289 }
290 
291 line *
292 setin(addr)
293 	line *addr;
294 {
295 
296 	if (addr == zero)
297 		lastin = 0;
298 	else
299 		getline(*addr), lastin = smunch(0, linebuf);
300 }
301