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