BSD 2 development
[unix-history] / src / ex / ex_cmds2.c
CommitLineData
9a067bbc
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#include "ex.h"
3#include "ex_argv.h"
4#include "ex_temp.h"
5#include "ex_tty.h"
6#include "ex_vis.h"
7
8bool pflag, nflag;
9int poffset;
10
11/*
12 * Subroutines for major command loop.
13 */
14
15/*
16 * Is there a single letter indicating a named buffer next?
17 */
18cmdreg()
19{
20 register int c = 0;
21
22 pastwh();
23 if (isalpha(peekchar()))
24 c = getchar();
25 return (c);
26}
27
28/*
29 * Tell whether the character ends a command
30 */
31endcmd(ch)
32 int ch;
33{
34 switch (ch) {
35
36 case '\n':
37 case EOF:
38 endline = 1;
39 return (1);
40
41 case '|':
42 endline = 0;
43 return (1);
44 }
45 return (0);
46}
47
48/*
49 * Insist on the end of the command.
50 */
51eol()
52{
53
54 if (!skipend())
55 error("Extra chars|Extra characters at end of command");
56 ignnEOF();
57}
58
59/*
60 * Print out the message in the error message file at str,
61 * with i an integer argument to printf.
62 */
63/*VARARGS2*/
64error(str, i)
65#ifdef lint
66 register char *str;
67#else
68 register int str;
69#endif
70 int i;
71{
72
73 error0();
74 merror(str, i);
75 error1(str);
76}
77
78/*
79 * Rewind the argument list.
80 */
81erewind()
82{
83
84 argc = argc0;
85 argv = argv0;
86 args = args0;
87 if (argc > 1 && !hush) {
88 printf(mesg("%d files@to edit"), argc);
89 if (inopen)
90 putchar(' ');
91 else
92 putNFL();
93 }
94}
95
96/*
97 * Guts of the pre-printing error processing.
98 * If in visual and catching errors, then we dont mung up the internals,
99 * just fixing up the echo area for the print.
100 * Otherwise we reset a number of externals, and discard unused input.
101 */
102error0()
103{
104
105 intag = 0;
106 if (vcatch) {
107 if (splitw == 0)
108 fixech();
109 if (!SO || !SE)
110 dingdong();
111 return;
112 }
113 if (input) {
114 input = strend(input) - 1;
115 if (*input == '\n')
116 setlastchar('\n');
117 input = 0;
118 }
119 setoutt();
120 flush();
121 resetflav();
122 if (laste) {
123 laste = 0;
124 sync();
125 }
126 if (!SO || !SE)
127 dingdong();
128 if (inopen) {
129 /*
130 * We are coming out of open/visual ungracefully.
131 * Restore COLUMNS, undo, and fix tty mode.
132 */
133 COLUMNS = OCOLUMNS;
134 undvis();
135 ostop(normf);
136 putpad(VE);
137 putnl();
138 }
139 inopen = 0;
140 holdcm = 0;
141}
142
143/*
144 * Post error printing processing.
145 * Close the i/o file if left open.
146 * If catching in visual then throw to the visual catch,
147 * else if a child after a fork, then exit.
148 * Otherwise, in the normal command mode error case,
149 * finish state reset, and throw to top.
150 */
151error1(str)
152 char *str;
153{
154
155 if (io > 0) {
156 close(io);
157 io = -1;
158 }
159 if (vcatch && !die) {
160 inglobal = 0;
161 inopen = 1;
162 vcatch = 0;
163 fixol();
164 longjmp(vreslab);
165 }
166 if (str)
167 putNFL();
168 if (die)
169 exit(1);
170 lseek(0, 0L, 2);
171 if (inglobal)
172 setlastchar('\n');
173 inglobal = 0;
174 globp = 0;
175 while (lastchar() != '\n' && lastchar() != EOF)
176 ignchar();
177 ungetchar(0);
178 endline = 1;
179 reset();
180}
181
182fixol()
183{
184 if (Outchar != vputchar) {
185 flush();
186 if (state == ONEOPEN || state == HARDOPEN)
187 outline = destline = 0;
188 Outchar = vputchar;
189 vcontin(1);
190 } else {
191 if (destcol)
192 vclreol();
193 vclean();
194 }
195}
196
197/*
198 * Does an ! character follow in the command stream?
199 */
200exclam()
201{
202
203 if (peekchar() == '!') {
204 ignchar();
205 return (1);
206 }
207 return (0);
208}
209
210/*
211 * Make an argument list for e.g. next.
212 */
213makargs()
214{
215
216 glob(&frob);
217 argc0 = frob.argc0;
218 argv0 = frob.argv;
219 args0 = argv0[0];
220 erewind();
221}
222
223/*
224 * Advance to next file in argument list.
225 */
226next()
227{
228
229 if (argc == 0)
230 error("No more files@to edit");
231 morargc = argc;
232 if (savedfile[0])
233 CP(altfile, savedfile);
234 CP(savedfile, args);
235 argc--;
236 args = argv ? *++argv : strend(args) + 1;
237}
238
239/*
240 * Eat trailing flags and offsets after a command,
241 * saving for possible later post-command prints.
242 */
243newline()
244{
245 register int c;
246
247 resetflav();
248 for (;;) {
249 c = getchar();
250 switch (c) {
251
252 case '^':
253 case '-':
254 poffset--;
255 break;
256
257 case '+':
258 poffset++;
259 break;
260
261 case 'l':
262 listf++;
263 break;
264
265 case '#':
266 nflag++;
267 break;
268
269 case 'p':
270 listf = 0;
271 break;
272
273 case ' ':
274 case '\t':
275 continue;
276
277 default:
278 if (!endcmd(c))
279 serror("Extra chars|Extra characters at end of \"%s\" command", Command);
280 if (c == EOF)
281 ungetchar(c);
282 setflav();
283 return;
284 }
285 pflag++;
286 }
287}
288
289/*
290 * Before quit or respec of arg list, check that there are
291 * no more files in the arg list.
292 */
293nomore()
294{
295
296 if (argc == 0 || morargc == argc)
297 return;
298 morargc = argc;
299 merror("%d more file", argc);
300 serror("%s@to edit", plural((long) argc));
301}
302
303/*
304 * Before edit of new file check that either an ! follows
305 * or the file has not been changed.
306 */
307quickly()
308{
309
310 if (exclam())
311 return (1);
312 if (chng) {
313/*
314 chng = 0;
315*/
316 xchng = 0;
317 error("No write@since last change (%s! overrides)", Command);
318 }
319 return (0);
320}
321
322/*
323 * Reset the flavor of the output to print mode with no numbering.
324 */
325resetflav()
326{
327
328 if (inopen)
329 return;
330 listf = 0;
331 nflag = 0;
332 pflag = 0;
333 poffset = 0;
334 setflav();
335}
336
337/*
338 * Print an error message with a %s type argument to printf.
339 * Message text comes from error message file.
340 */
341serror(str, cp)
342#ifdef lint
343 register char *str;
344#else
345 register int str;
346#endif
347 char *cp;
348{
349
350 error0();
351 smerror(str, cp);
352 error1(str);
353}
354
355/*
356 * Set the flavor of the output based on the flags given
357 * and the number and list options to either number or not number lines
358 * and either use normally decoded (ARPAnet standard) characters or list mode,
359 * where end of lines are marked and tabs print as ^I.
360 */
361setflav()
362{
363
364 if (inopen)
365 return;
366 setnumb(nflag || value(NUMBER));
367 setlist(listf || value(LIST));
368 setoutt();
369}
370
371/*
372 * Skip white space and tell whether command ends then.
373 */
374skipend()
375{
376
377 pastwh();
378 return (endcmd(peekchar()));
379}
380
381/*
382 * Set the command name for non-word commands.
383 */
384tailspec(c)
385 int c;
386{
387 static char foocmd[2];
388
389 foocmd[0] = c;
390 Command = foocmd;
391}
392
393/*
394 * Try to read off the rest of the command word.
395 * If alphabetics follow, then this is not the command we seek.
396 */
397tail(comm)
398 char *comm;
399{
400
401 tailprim(comm, 1, 0);
402}
403
404tail2of(comm)
405 char *comm;
406{
407
408 tailprim(comm, 2, 0);
409}
410
411char tcommand[20];
412
413tailprim(comm, i, notinvis)
414 register char *comm;
415 int i;
416 bool notinvis;
417{
418 register char *cp;
419 register int c;
420
421 Command = comm;
422 for (cp = tcommand; i > 0; i--)
423 *cp++ = *comm++;
424 while (*comm && peekchar() == *comm)
425 *cp++ = getchar(), comm++;
426 c = peekchar();
427 if (notinvis || isalpha(c)) {
428 /*
429 * Of the trailing lp funny buisness, only dl and dp
430 * survive the move from ed to ex.
431 */
432 if (tcommand[0] == 'd' && any(c, "lp"))
433 goto ret;
434 while (cp < &tcommand[19] && isalpha(peekchar()))
435 *cp++ = getchar();
436 *cp = 0;
437 if (notinvis)
438 serror("What?|%s: No such command from open/visual", tcommand);
439 else
440 serror("What?|%s: Not an editor command", tcommand);
441 }
442ret:
443 *cp = 0;
444}
445
446/*
447 * Continue after a shell escape from open/visual.
448 */
449vcontin(ask)
450 bool ask;
451{
452
453 if (vcnt > 0)
454 vcnt = -vcnt;
455 if (inopen) {
456 if (state != VISUAL) {
457/*
458 vtube[WECHO][0] = '*';
459 vnfl();
460*/
461 return;
462 }
463 if (ask) {
464 merror("[Hit return to continue] ");
465 flush();
466 }
467#ifdef V6
468 vraw();
469#endif
470 if (ask && getkey() == ':')
471 ungetkey(':');
472 }
473}
474
475/*
476 * Put out a newline (before a shell escape)
477 * if in open/visual.
478 */
479vnfl()
480{
481
482 if (inopen) {
483 if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
484 vclean();
485 else
486 vmoveitup(1);
487 vgoto(WECHO, 0);
488 vclrbyte(vtube[WECHO], WCOLS);
489 flush();
490 }
491}