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