Subversion Repositories planix.SVN

Rev

Rev 113 | Details | Compare with Previous | Last modification | View Log | RSS feed

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