4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / ex / ex_get.c
CommitLineData
2791ff57 1/*-
eb035710
KB
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
2791ff57
KB
4 *
5 * %sccs.include.proprietary.c%
19d73a0e
DF
6 */
7
8#ifndef lint
eb035710 9static char sccsid[] = "@(#)ex_get.c 8.1 (Berkeley) %G%";
2791ff57 10#endif /* not lint */
19d73a0e 11
61b2d8db
MH
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 */
20static bool junkbs;
21short lastc = '\n';
22
23ignchar()
24{
5a6c967e 25 ignore(ex_getchar());
61b2d8db
MH
26}
27
5a6c967e 28ex_getchar()
61b2d8db
MH
29{
30 register int c;
31
32 do
33 c = getcd();
65bacefd 34 while (!globp && c == CTRL('d'));
61b2d8db
MH
35 return (c);
36}
37
38getcd()
39{
40 register int c;
41
42again:
43 c = getach();
44 if (c == EOF)
45 return (c);
46 c &= TRIM;
47 if (!inopen)
65bacefd 48 if (!globp && c == CTRL('d'))
61b2d8db
MH
49 setlastchar('\n');
50 else if (junk(c)) {
51 checkjunk(c);
52 goto again;
53 }
54 return (c);
55}
56
57peekchar()
58{
59
60 if (peekc == 0)
5a6c967e 61 peekc = ex_getchar();
61b2d8db
MH
62 return (peekc);
63}
64
65peekcd()
66{
61b2d8db
MH
67 if (peekc == 0)
68 peekc = getcd();
69 return (peekc);
70}
71
72getach()
73{
74 register int c;
13c5231e 75 static char inputline[BUFSIZ];
61b2d8db
MH
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 }
88top:
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();
f4f348a0 98 if (intty) {
13c5231e 99 c = read(0, inputline, sizeof inputline - 4);
61b2d8db
MH
100 if (c < 0)
101 return (lastc = EOF);
13c5231e
KB
102 if (c == 0 || inputline[c-1] != '\n')
103 inputline[c++] = CTRL('d');
104 if (inputline[c-1] == '\n')
61b2d8db 105 noteinp();
13c5231e 106 inputline[c] = 0;
61b2d8db 107 for (c--; c >= 0; c--)
13c5231e
KB
108 if (inputline[c] == 0)
109 inputline[c] = QUOTE;
110 input = inputline;
61b2d8db
MH
111 goto top;
112 }
13c5231e 113 c = read(0, inputline, sizeof inputline - 1);
0567d6e3
RC
114 if(c <= 0)
115 return(lastc = EOF);
13c5231e
KB
116 inputline[c] = '\0';
117 input = inputline;
0567d6e3 118 goto top;
61b2d8db
MH
119}
120
121/*
122 * Input routine for insert/append/change in command mode.
123 * Most work here is in handling autoindent.
124 */
125static short lastin;
126
127gettty()
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;
5a6c967e 140 ex_printf(" %4d ", lineDOT() + 1);
61b2d8db
MH
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);
65bacefd 151 while ((c = getcd()) == CTRL('d')) {
61b2d8db
MH
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();
65bacefd 164 if (ch == CTRL('d')) {
61b2d8db
MH
165 if (c == '0')
166 lastin = 0;
167 if (!OS) {
5a6c967e
CH
168 ex_putchar('\b' | QUOTE);
169 ex_putchar(' ' | QUOTE);
170 ex_putchar('\b' | QUOTE);
61b2d8db
MH
171 }
172 tab(offset);
173 hadup = 1;
5a6c967e 174 c = ex_getchar();
61b2d8db
MH
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)
5a6c967e 197 c = ex_getchar();
61b2d8db
MH
198 while (c != EOF && c != '\n') {
199 if (cp > &genbuf[LBSIZE - 2])
200 error("Input line too long");
201 *cp++ = c;
5a6c967e 202 c = ex_getchar();
61b2d8db
MH
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 */
231smunch(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
256char *cntrlhm = "^H discarded\n";
257
258checkjunk(c)
259 char c;
260{
261
262 if (junkbs == 0 && c == '\b') {
263 write(2, cntrlhm, 13);
264 junkbs = 1;
265 }
266}
267
268line *
269setin(addr)
270 line *addr;
271{
272
273 if (addr == zero)
274 lastin = 0;
275 else
276 getline(*addr), lastin = smunch(0, linebuf);
277}