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