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