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