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