BSD 3 development
[unix-history] / usr / src / cmd / ex / ex_cmds2.c
CommitLineData
27704fe4
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 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 '|':
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 if (vcatch) {
106 if (splitw == 0)
107 fixech();
108 if (!SO || !SE)
109 dingdong();
110 return;
111 }
112 if (input) {
113 input = strend(input) - 1;
114 if (*input == '\n')
115 setlastchar('\n');
116 input = 0;
117 }
118 setoutt();
119 flush();
120 resetflav();
121 if (laste) {
122 laste = 0;
123 sync();
124 }
125 if (!SO || !SE)
126 dingdong();
127 if (inopen) {
128 /*
129 * We are coming out of open/visual ungracefully.
130 * Restore COLUMNS, undo, and fix tty mode.
131 */
132 COLUMNS = OCOLUMNS;
133 undvis();
134 ostop(normf);
135 putpad(VE);
136 putpad(KE);
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 bool die;
155
156 if (io > 0) {
157 close(io);
158 io = -1;
159 }
160 die = (getpid() != ppid); /* Only children die */
161 if (vcatch && !die) {
162 inglobal = 0;
163 vglobp = vmacp = 0;
164 inopen = 1;
165 vcatch = 0;
166 fixol();
167 longjmp(vreslab,1);
168 }
169 if (str && !vcatch)
170 putNFL();
171 if (die)
172 exit(1);
173 lseek(0, 0L, 2);
174 if (inglobal)
175 setlastchar('\n');
176 inglobal = 0;
177 globp = 0;
178 while (lastchar() != '\n' && lastchar() != EOF)
179 ignchar();
180 ungetchar(0);
181 endline = 1;
182 reset();
183}
184
185fixol()
186{
187 if (Outchar != vputchar) {
188 flush();
189 if (state == ONEOPEN || state == HARDOPEN)
190 outline = destline = 0;
191 Outchar = vputchar;
192 vcontin(1);
193 } else {
194 if (destcol)
195 vclreol();
196 vclean();
197 }
198}
199
200/*
201 * Does an ! character follow in the command stream?
202 */
203exclam()
204{
205
206 if (peekchar() == '!') {
207 ignchar();
208 return (1);
209 }
210 return (0);
211}
212
213/*
214 * Make an argument list for e.g. next.
215 */
216makargs()
217{
218
219 glob(&frob);
220 argc0 = frob.argc0;
221 argv0 = frob.argv;
222 args0 = argv0[0];
223 erewind();
224}
225
226/*
227 * Advance to next file in argument list.
228 */
229next()
230{
231
232 if (argc == 0)
233 error("No more files@to edit");
234 morargc = argc;
235 if (savedfile[0])
236 CP(altfile, savedfile);
237 CP(savedfile, args);
238 argc--;
239 args = argv ? *++argv : strend(args) + 1;
240}
241
242/*
243 * Eat trailing flags and offsets after a command,
244 * saving for possible later post-command prints.
245 */
246newline()
247{
248 register int c;
249
250 resetflav();
251 for (;;) {
252 c = getchar();
253 switch (c) {
254
255 case '^':
256 case '-':
257 poffset--;
258 break;
259
260 case '+':
261 poffset++;
262 break;
263
264 case 'l':
265 listf++;
266 break;
267
268 case '#':
269 nflag++;
270 break;
271
272 case 'p':
273 listf = 0;
274 break;
275
276 case ' ':
277 case '\t':
278 continue;
279
280 default:
281 if (!endcmd(c))
282serror("Extra chars|Extra characters at end of \"%s\" command", Command);
283 if (c == EOF)
284 ungetchar(c);
285 setflav();
286 return;
287 }
288 pflag++;
289 }
290}
291
292/*
293 * Before quit or respec of arg list, check that there are
294 * no more files in the arg list.
295 */
296nomore()
297{
298
299 if (argc == 0 || morargc == argc)
300 return;
301 morargc = argc;
302 merror("%d more file", argc);
303 serror("%s@to edit", plural((long) argc));
304}
305
306/*
307 * Before edit of new file check that either an ! follows
308 * or the file has not been changed.
309 */
310quickly()
311{
312
313 if (exclam())
314 return (1);
315 if (chng && dol > zero) {
316/*
317 chng = 0;
318*/
319 xchng = 0;
320 error("No write@since last change (:%s! overrides)", Command);
321 }
322 return (0);
323}
324
325/*
326 * Reset the flavor of the output to print mode with no numbering.
327 */
328resetflav()
329{
330
331 if (inopen)
332 return;
333 listf = 0;
334 nflag = 0;
335 pflag = 0;
336 poffset = 0;
337 setflav();
338}
339
340/*
341 * Print an error message with a %s type argument to printf.
342 * Message text comes from error message file.
343 */
344serror(str, cp)
345#ifdef lint
346 register char *str;
347#else
348 register int str;
349#endif
350 char *cp;
351{
352
353 error0();
354 smerror(str, cp);
355 error1(str);
356}
357
358/*
359 * Set the flavor of the output based on the flags given
360 * and the number and list options to either number or not number lines
361 * and either use normally decoded (ARPAnet standard) characters or list mode,
362 * where end of lines are marked and tabs print as ^I.
363 */
364setflav()
365{
366
367 if (inopen)
368 return;
369 setnumb(nflag || value(NUMBER));
370 setlist(listf || value(LIST));
371 setoutt();
372}
373
374/*
375 * Skip white space and tell whether command ends then.
376 */
377skipend()
378{
379
380 pastwh();
381 return (endcmd(peekchar()));
382}
383
384/*
385 * Set the command name for non-word commands.
386 */
387tailspec(c)
388 int c;
389{
390 static char foocmd[2];
391
392 foocmd[0] = c;
393 Command = foocmd;
394}
395
396/*
397 * Try to read off the rest of the command word.
398 * If alphabetics follow, then this is not the command we seek.
399 */
400tail(comm)
401 char *comm;
402{
403
404 tailprim(comm, 1, 0);
405}
406
407tail2of(comm)
408 char *comm;
409{
410
411 tailprim(comm, 2, 0);
412}
413
414char tcommand[20];
415
416tailprim(comm, i, notinvis)
417 register char *comm;
418 int i;
419 bool notinvis;
420{
421 register char *cp;
422 register int c;
423
424 Command = comm;
425 for (cp = tcommand; i > 0; i--)
426 *cp++ = *comm++;
427 while (*comm && peekchar() == *comm)
428 *cp++ = getchar(), comm++;
429 c = peekchar();
430 if (notinvis || isalpha(c)) {
431 /*
432 * Of the trailing lp funny business, only dl and dp
433 * survive the move from ed to ex.
434 */
435 if (tcommand[0] == 'd' && any(c, "lp"))
436 goto ret;
437 if (tcommand[0] == 's' && any(c, "gcr"))
438 goto ret;
439 while (cp < &tcommand[19] && isalpha(peekchar()))
440 *cp++ = getchar();
441 *cp = 0;
442 if (notinvis)
443 serror("What?|%s: No such command from open/visual", tcommand);
444 else
445 serror("What?|%s: Not an editor command", tcommand);
446 }
447ret:
448 *cp = 0;
449}
450
451/*
452 * Continue after a shell escape from open/visual.
453 */
454vcontin(ask)
455 bool ask;
456{
457
458 if (vcnt > 0)
459 vcnt = -vcnt;
460 if (inopen) {
461 if (state != VISUAL) {
462/*
463 vtube[WECHO][0] = '*';
464 vnfl();
465*/
466 return;
467 }
468 if (ask) {
469 merror("[Hit return to continue] ");
470 flush();
471 }
472#ifndef CBREAK
473 vraw();
474#endif
475 if (ask) {
476 /*
477 * Gobble ^Q/^S since the tty driver should be eating
478 * them (as far as the user can see)
479 */
480 while (peekkey() == CTRL(Q) || peekkey() == CTRL(S))
481 ignore(getkey());
482 if(getkey() == ':')
483 ungetkey(':');
484 }
485 putpad(VS);
486 putpad(KS);
487 }
488}
489
490/*
491 * Put out a newline (before a shell escape)
492 * if in open/visual.
493 */
494vnfl()
495{
496
497 if (inopen) {
498 if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
499 vclean();
500 else
501 vmoveitup(1, 0);
502 vgoto(WECHO, 0);
503 vclrbyte(vtube[WECHO], WCOLS);
504 putpad(VE);
505 putpad(KE);
506 }
507 flush();
508}