Commit | Line | Data |
---|---|---|
5e6208eb BJ |
1 | #include "ex.h" |
2 | #ifdef VISUAL | |
3 | #include "ex_tty.h" | |
4 | #include "ex_vis.h" | |
5 | /* | |
6 | * Ex - a text editor | |
7 | * Bill Joy UCB September 1977 | |
8 | */ | |
9 | ||
10 | #define blank() white(wcursor[0]) | |
11 | ||
12 | int beep(), vmove(), vdelete(), vchange(), vyankit(), vgrabit(); | |
13 | ||
14 | operate(c, cnt) | |
15 | register int c, cnt; | |
16 | { | |
17 | register int i; | |
18 | int (*moveop)(), (*deleteop)(), listchar(); | |
19 | register int (*op)(); | |
20 | extern int (*Putchar)(); | |
21 | char subop; | |
22 | static char lastFKND, lastFCHR; | |
23 | ||
24 | moveop = vmove; | |
25 | deleteop = vdelete; | |
26 | wcursor = cursor; | |
27 | dir = 1; | |
28 | subop = 0; | |
29 | switch (c) { | |
30 | case '@': | |
31 | case CTRL(x): | |
32 | wcursor = linebuf; | |
33 | vdelete('@'); | |
34 | return; | |
35 | case 'd': | |
36 | moveop = vdelete; | |
37 | deleteop = beep; | |
38 | break; | |
39 | case 's': | |
40 | ungetkey(' '); | |
41 | subop++; | |
42 | case 'c': | |
43 | if (c == 'c' && workcmd[0] == 'C') | |
44 | subop++; | |
45 | moveop = vchange; | |
46 | deleteop = beep; | |
47 | break; | |
48 | case 'y': | |
49 | moveop = vyankit; | |
50 | deleteop = beep; | |
51 | break; | |
52 | case 'g': | |
53 | moveop = vgrabit; | |
54 | deleteop = beep; | |
55 | break; | |
56 | case 'r': | |
57 | if (cnt > strlen(cursor)) | |
58 | goto errlab; | |
59 | if (*cursor == '\t' || Putchar == &listchar) | |
60 | vgotoCL(column(cursor - 1)); | |
61 | c = getesc(); | |
62 | if (c == 0) { | |
63 | vfixcurs(); | |
64 | return; | |
65 | } | |
66 | ungetkey(c); | |
67 | strcpy(vutmp, linebuf); | |
68 | vundkind = VCHNG; | |
69 | wcursor = cursor + cnt; | |
70 | setLAST(); | |
71 | strcpy(cursor, wcursor); | |
72 | vappend('r', cnt, 0); | |
73 | *lastcp++ = c; | |
74 | setLAST(); | |
75 | return; | |
76 | default: | |
77 | goto nocount; | |
78 | } | |
79 | if (digit(peekkey()) && peekkey() != '0') { | |
80 | cnt =* vgetcnt(); | |
81 | Xcnt = cnt; | |
82 | if (cnt < 0) { | |
83 | beep(); | |
84 | return; | |
85 | } | |
86 | } | |
87 | c = getesc(); | |
88 | if (c == 0) | |
89 | return; | |
90 | if (!subop) | |
91 | *lastcp++ = c; | |
92 | if (NDSPACE && NDSPACE[0] == c && NDSPACE[1] == 0) | |
93 | goto space; | |
94 | nocount: | |
95 | switch (c) { | |
96 | case CTRL(w): | |
97 | c = 'B'; | |
98 | case 'b': | |
99 | case 'B': | |
100 | dir = -1; | |
101 | case 'W': | |
102 | case 'w': | |
103 | wdkind = c & ' '; | |
104 | op = moveop; | |
105 | if (edge()) | |
106 | goto errlab; | |
107 | while (cnt > 0 && !edge()) { | |
108 | word(op, cnt); | |
109 | cnt--; | |
110 | } | |
111 | break; | |
112 | #ifdef UNIMP | |
113 | case 'E': | |
114 | dir = -1; | |
115 | case 'e': | |
116 | wdkind = 1; | |
117 | op = moveop; | |
118 | if (edge()) | |
119 | goto errlab; | |
120 | while (cnt > 1 && !edge()) { | |
121 | word(op, cnt); | |
122 | cnt--; | |
123 | } | |
124 | eend(op, cnt); | |
125 | break; | |
126 | #endif | |
127 | case '0': | |
128 | wcursor = linebuf; | |
129 | op = moveop; | |
130 | break; | |
131 | case ';': | |
132 | if (lastFKND == 0) { | |
133 | beep(); | |
134 | return; | |
135 | } | |
136 | c = lastFKND; | |
137 | ungetkey(lastFCHR); | |
138 | subop++; | |
139 | goto nocount; | |
140 | case 'F': /* inverted find */ | |
141 | case 'T': | |
142 | dir = -1; | |
143 | case 'f': /* find */ | |
144 | case 't': | |
145 | i = getesc(); | |
146 | if (i == 0) | |
147 | return; | |
148 | if (!subop) | |
149 | *lastcp++ = i; | |
150 | lastFKND = c; | |
151 | lastFCHR = i; | |
152 | while (cnt > 0) { | |
153 | if (find(i) == 0) | |
154 | goto errlab; | |
155 | cnt--; | |
156 | } | |
157 | switch (c) { | |
158 | case 'T': | |
159 | wcursor++; | |
160 | break; | |
161 | case 't': | |
162 | wcursor--; | |
163 | case 'f': | |
164 | fixup: | |
165 | if (moveop != vmove) | |
166 | wcursor++; | |
167 | break; | |
168 | } | |
169 | op = moveop; | |
170 | break; | |
171 | case '|': | |
172 | if (Xhadcnt) { | |
173 | if (Pline == &numbline) | |
174 | cnt =+ 8; | |
175 | vmovcol = cnt; | |
176 | } | |
177 | vmoving = 1; | |
178 | wcursor = vfindcol(cnt); | |
179 | op = moveop; | |
180 | break; | |
181 | case '^': | |
182 | wcursor = vskipwh(linebuf); | |
183 | op = moveop; | |
184 | break; | |
185 | case '$': | |
186 | wcursor = strend(linebuf) - 1; | |
187 | goto fixup; | |
188 | case 'h': | |
189 | case CTRL(h): | |
190 | dir = -1; | |
191 | case ' ': | |
192 | space: | |
193 | case 'l': | |
194 | op = moveop; | |
195 | if (margin() || op == &vmove && edge()) | |
196 | goto errlab; | |
197 | moveit: | |
198 | while (cnt > 0 && !margin()) { | |
199 | wcursor =+ dir; | |
200 | cnt--; | |
201 | } | |
202 | if (margin() && op == &vmove || wcursor < linebuf) | |
203 | wcursor =- dir; | |
204 | break; | |
205 | case 'D': | |
206 | cnt = INF; | |
207 | goto deleteit; | |
208 | case 'X': /* inverted delete */ | |
209 | case '#': /* "oex" delete */ | |
210 | dir = -1; | |
211 | deleteit: | |
212 | case 'x': /* delete */ | |
213 | if (margin()) | |
214 | goto errlab; | |
215 | while (cnt > 0 && !margin()) { | |
216 | wcursor =+ dir; | |
217 | cnt--; | |
218 | } | |
219 | op = deleteop; | |
220 | break; | |
221 | default: | |
222 | errlab: | |
223 | beep(); | |
224 | return; | |
225 | } | |
226 | (*op)(c); | |
227 | } | |
228 | ||
229 | find(c) | |
230 | char c; | |
231 | { | |
232 | ||
233 | for(;;) { | |
234 | if (edge()) | |
235 | return (0); | |
236 | wcursor =+ dir; | |
237 | if (*wcursor == c) | |
238 | return (1); | |
239 | } | |
240 | } | |
241 | ||
242 | word(op, cnt) | |
243 | register int (*op)(); | |
244 | int cnt; | |
245 | { | |
246 | register int which; | |
247 | register char *iwc; | |
248 | ||
249 | if (dir == 1) { | |
250 | iwc = wcursor; | |
251 | /* | |
252 | * Word going forward. | |
253 | * Determine whether the character under | |
254 | * the cursor is a "word" character. | |
255 | * If it is, skip through such | |
256 | * else through nonesuch. | |
257 | */ | |
258 | which = wordch(wcursor); | |
259 | while (!margin() && wordof(which, wcursor)) | |
260 | wcursor++; | |
261 | /* | |
262 | * Unless this the last segment of a change | |
263 | * we want to skip blanks. | |
264 | */ | |
265 | if (op != vchange || cnt > 1) | |
266 | while (!margin() && blank()) | |
267 | wcursor++; | |
268 | else | |
269 | if (wcursor == iwc && *iwc) | |
270 | wcursor++; | |
271 | /* | |
272 | * Can't move off end | |
273 | */ | |
274 | if (op == vmove && margin()) | |
275 | wcursor--; | |
276 | } else { | |
277 | /* | |
278 | * Word going backwards. | |
279 | * First skip through blanks, then through word | |
280 | * or non-word characters. | |
281 | */ | |
282 | wcursor--; | |
283 | while (!margin() && blank()) | |
284 | wcursor--; | |
285 | if (!margin()) { | |
286 | which = wordch(wcursor); | |
287 | while (!margin() && wordof(which, wcursor)) | |
288 | wcursor--; | |
289 | } | |
290 | if (margin() || !wordof(which, wcursor)) | |
291 | wcursor++; | |
292 | } | |
293 | } | |
294 | ||
295 | #ifdef UNIMP | |
296 | eend(op, cnt) | |
297 | register int (*op)(); | |
298 | int cnt; | |
299 | { | |
300 | register int which; | |
301 | register char *iwc; | |
302 | ||
303 | if (dir == 1) { | |
304 | if (!margin()) | |
305 | wcursor++; | |
306 | while (!margin() && blank()) | |
307 | wcursor++; | |
308 | which = wordch(wcursor); | |
309 | while (!margin() && wordof(which, wcursor)) | |
310 | wcursor++; | |
311 | if (cnt == 1 && op != &vchange && op != &vdelete) | |
312 | wcursor--; | |
313 | } else { | |
314 | if (!blank()) { | |
315 | which = wordch(wcursor); | |
316 | while (!margin() && wordof(which, wcursor)) | |
317 | wcursor--; | |
318 | } | |
319 | while (!margin() && blank()) | |
320 | wcursor--; | |
321 | if (margin()) | |
322 | wcursor++; | |
323 | } | |
324 | } | |
325 | #endif | |
326 | ||
327 | wordof(which, wcursor) | |
328 | char which, *wcursor; | |
329 | { | |
330 | ||
331 | if (white(*wcursor)) | |
332 | return (0); | |
333 | return (!wdkind || wordch(wcursor) == which); | |
334 | } | |
335 | ||
336 | wordch(wcursor) | |
337 | char *wcursor; | |
338 | { | |
339 | register int c; | |
340 | ||
341 | c = wcursor[0]; | |
342 | return (letter(c) || digit(c) || c == '_'); | |
343 | } | |
344 | ||
345 | edge() | |
346 | { | |
347 | ||
348 | if (linebuf[0] == 0) | |
349 | return (1); | |
350 | if (dir == 1) | |
351 | return (wcursor[1] == 0); | |
352 | else | |
353 | return (wcursor == linebuf); | |
354 | } | |
355 | ||
356 | margin() | |
357 | { | |
358 | ||
359 | return (wcursor < linebuf || wcursor[0] == 0); | |
360 | } | |
361 | ||
362 | beep() | |
363 | { | |
364 | vputc('\07'); | |
365 | } | |
366 | #endif |