Commit | Line | Data |
---|---|---|
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 | 8 | static 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 | */ | |
19 | static bool junkbs; | |
20 | short lastc = '\n'; | |
21 | ||
22 | ignchar() | |
23 | { | |
5a6c967e | 24 | ignore(ex_getchar()); |
61b2d8db MH |
25 | } |
26 | ||
5a6c967e | 27 | ex_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 | ||
37 | getcd() | |
38 | { | |
39 | register int c; | |
40 | ||
41 | again: | |
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 | ||
56 | peekchar() | |
57 | { | |
58 | ||
59 | if (peekc == 0) | |
5a6c967e | 60 | peekc = ex_getchar(); |
61b2d8db MH |
61 | return (peekc); |
62 | } | |
63 | ||
64 | peekcd() | |
65 | { | |
61b2d8db MH |
66 | if (peekc == 0) |
67 | peekc = getcd(); | |
68 | return (peekc); | |
69 | } | |
70 | ||
71 | getach() | |
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 | } | |
87 | top: | |
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 | */ | |
124 | static short lastin; | |
125 | ||
126 | gettty() | |
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 | */ | |
230 | smunch(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 | ||
255 | char *cntrlhm = "^H discarded\n"; | |
256 | ||
257 | checkjunk(c) | |
258 | char c; | |
259 | { | |
260 | ||
261 | if (junkbs == 0 && c == '\b') { | |
262 | write(2, cntrlhm, 13); | |
263 | junkbs = 1; | |
264 | } | |
265 | } | |
266 | ||
267 | line * | |
268 | setin(addr) | |
269 | line *addr; | |
270 | { | |
271 | ||
272 | if (addr == zero) | |
273 | lastin = 0; | |
274 | else | |
275 | getline(*addr), lastin = smunch(0, linebuf); | |
276 | } |