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