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