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_vops2.c	6.8 (Berkeley) 6/7/85";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_tty.h"
13
#include "ex_vis.h"
14
 
15
/*
16
 * Low level routines for operations sequences,
17
 * and mostly, insert mode (and a subroutine
18
 * to read an input line, including in the echo area.)
19
 */
20
extern char	*vUA1, *vUA2;		/* mjm: extern; also in ex_vops.c */
21
extern char	*vUD1, *vUD2;		/* mjm: extern; also in ex_vops.c */
22
 
23
/*
24
 * Obleeperate characters in hardcopy
25
 * open with \'s.
26
 */
27
bleep(i, cp)
28
	register int i;
29
	char *cp;
30
{
31
 
32
	i -= column(cp);
33
	do
34
#ifndef	ISO
35
		putchar('\\' | QUOTE);
36
#else
37
		putchar('\\');
38
#endif
39
	while (--i >= 0);
40
	rubble = 1;
41
}
42
 
43
/*
44
 * Common code for middle part of delete
45
 * and change operating on parts of lines.
46
 */
47
vdcMID()
48
{
49
	register char *cp;
50
 
51
	squish();
52
	setLAST();
53
	if (FIXUNDO)
54
#ifndef	BIT8
115 7u83 55
		vundkind = VCHNG, CP(vutmp, linebuf);
105 7u83 56
#else
57
		vundkind = VCHNG, sc_strcpy(vutmp, linebuf);
58
#endif
59
	if (wcursor < cursor)
60
		cp = wcursor, wcursor = cursor, cursor = cp;
61
	vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
62
	return (column(wcursor - 1));
63
}
64
 
65
/*
66
 * Take text from linebuf and stick it
67
 * in the VBSIZE buffer BUF.  Used to save
68
 * deleted text of part of line.
69
 */
70
takeout(BUF)
71
	char *BUF;
72
{
73
	register char *cp;
74
 
75
	if (wcursor < linebuf)
76
		wcursor = linebuf;
77
	if (cursor == wcursor) {
78
		beep();
79
		return;
80
	}
81
	if (wcursor < cursor) {
82
		cp = wcursor;
83
		wcursor = cursor;
84
		cursor = cp;
85
	}
86
	setBUF(BUF);
87
	if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
88
		beep();
89
}
90
 
91
/*
92
 * Are we at the end of the printed representation of the
93
 * line?  Used internally in hardcopy open.
94
 */
95
ateopr()
96
{
97
	register int i, c;
98
#ifndef	BIT8
99
	register char *cp = vtube[destline] + destcol;
100
#else
101
	register short *cp = vtube[destline] + destcol;
102
#endif
103
 
104
	for (i = WCOLS - destcol; i > 0; i--) {
105
		c = *cp++;
106
		if (c == 0)
107
			return (1);
108
#ifdef	ISO
109
		if ((c & QUOTE) && !niso(c))
110
			return (0);
111
#endif
112
		if (c != ' ' && (c & QUOTE) == 0)
113
			return (0);
114
	}
115
	return (1);
116
}
117
 
118
/*
119
 * Append.
120
 *
121
 * This routine handles the top level append, doing work
122
 * as each new line comes in, and arranging repeatability.
123
 * It also handles append with repeat counts, and calculation
124
 * of autoindents for new lines.
125
 */
126
bool	vaifirst;
127
bool	gobbled;
128
char	*ogcursor;
129
 
130
vappend(ch, cnt, indent)
131
	int ch;		/* mjm: char --> int */
132
	int cnt, indent;
133
{
134
	register int i;
135
	register char *gcursor;
136
	bool escape;
137
	int repcnt, savedoomed;
138
	short oldhold = hold;
139
	long oldmask;
140
 
141
	/*
142
	 * Before a move in hardopen when the line is dirty
143
	 * or we are in the middle of the printed representation,
144
	 * we retype the line to the left of the cursor so the
145
	 * insert looks clean.
146
	 */
147
	if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
148
		rubble = 1;
149
		gcursor = cursor;
150
		i = *gcursor;
151
		*gcursor = ' ';
152
		wcursor = gcursor;
153
		vmove();
154
		*gcursor = i;
155
	}
156
	vaifirst = indent == 0;
157
 
158
	/*
159
	 * Handle replace character by (eventually)
160
	 * limiting the number of input characters allowed
161
	 * in the vgetline routine.
162
	 */
163
	if (ch == 'r')
164
		repcnt = 2;
165
	else
166
		repcnt = 0;
167
 
168
	/*
169
	 * If an autoindent is specified, then
170
	 * generate a mixture of blanks to tabs to implement
171
	 * it and place the cursor after the indent.
172
	 * Text read by the vgetline routine will be placed in genbuf,
173
	 * so the indent is generated there.
174
	 */
175
	if (value(AUTOINDENT) && indent != 0) {
176
		gcursor = genindent(indent);
177
		*gcursor = 0;
178
		vgotoCL(qcolumn(cursor - 1, genbuf));
179
	} else {
180
		gcursor = genbuf;
181
		*gcursor = 0;
182
		if (ch == 'o')
183
			vfixcurs();
184
	}
185
 
186
	/*
187
	 * Prepare for undo.  Pointers delimit inserted portion of line.
188
	 */
189
	vUA1 = vUA2 = cursor;
190
 
191
	/*
192
	 * If we are not in a repeated command and a ^@ comes in
193
	 * then this means the previous inserted text.
194
	 * If there is none or it was too long to be saved,
195
	 * then beep() and also arrange to undo any damage done
196
	 * so far (e.g. if we are a change.)
197
	 */
198
	if ((vglobp && *vglobp == 0) || peekbr()) {
199
		if ((INS[0] & (QUOTE|TRIM)) == OVERBUF) {
200
			beep();
201
			if (!splitw)
202
				ungetkey('u');
203
			doomed = 0;
204
			hold = oldhold;
205
			return;
206
		}
207
		/*
208
		 * Unread input from INS.
209
		 * An escape will be generated at end of string.
210
		 * Hold off n^^2 type update on dumb terminals.
211
		 */
212
		vglobp = INS;
213
		hold |= HOLDQIK;
214
	} else if (vglobp == 0)
215
		/*
216
		 * Not a repeated command, get
217
		 * a new inserted text for repeat.
218
		 */
219
		INS[0] = 0;
220
 
221
	/*
222
	 * For wrapmargin to hack away second space after a '.'
223
	 * when the first space caused a line break we keep
224
	 * track that this happened in gobblebl, which says
225
	 * to gobble up a blank silently.
226
	 */
227
	gobblebl = 0;
228
 
107 7u83 229
/* XXX	oldmask = sigblock(sigmask(SIGWINCH)); */
105 7u83 230
	/*
231
	 * Text gathering loop.
232
	 * New text goes into genbuf starting at gcursor.
233
	 * cursor preserves place in linebuf where text will eventually go.
234
	 */
235
	if (*cursor == 0 || state == CRTOPEN)
236
		hold |= HOLDROL;
237
	for (;;) {
238
		if (ch == 'r' && repcnt == 0)
239
			escape = 0;
240
		else {
241
			gcursor = vgetline(repcnt, gcursor, &escape, ch);
242
 
243
			/*
244
			 * After an append, stick information
245
			 * about the ^D's and ^^D's and 0^D's in
246
			 * the repeated text buffer so repeated
247
			 * inserts of stuff indented with ^D as backtab's
248
			 * can work.
249
			 */
250
			if (HADUP)
251
				addtext("^");
252
			else if (HADZERO)
253
				addtext("0");
254
			while (CDCNT > 0)
255
				addtext("\204"), CDCNT--;
256
			if (gobbled)
257
				addtext(" ");
258
			addtext(ogcursor);
259
		}
260
		repcnt = 0;
261
 
262
		/*
263
		 * Smash the generated and preexisting indents together
264
		 * and generate one cleanly made out of tabs and spaces
265
		 * if we are using autoindent.
266
		 */
267
		if (!vaifirst && value(AUTOINDENT)) {
268
			i = fixindent(indent);
269
			if (!HADUP)
270
				indent = i;
271
			gcursor = strend(genbuf);
272
		}
273
 
274
		/*
275
		 * Limit the repetition count based on maximum
276
		 * possible line length; do output implied
277
		 * by further count (> 1) and cons up the new line
278
		 * in linebuf.
279
		 */
280
		cnt = vmaxrep(ch, cnt);
115 7u83 281
		CP(gcursor + 1, cursor);
105 7u83 282
		do {
115 7u83 283
			CP(cursor, genbuf);
105 7u83 284
			if (cnt > 1) {
285
				int oldhold = hold;
286
 
287
				Outchar = vinschar;
288
				hold |= HOLDQIK;
289
				printf("%s", genbuf);
290
				hold = oldhold;
291
				Outchar = vputchar;
292
			}
293
			cursor += gcursor - genbuf;
294
		} while (--cnt > 0);
295
		endim();
296
		vUA2 = cursor;
297
		if (escape != '\n')
115 7u83 298
			CP(cursor, gcursor + 1);
105 7u83 299
 
300
		/*
301
		 * If doomed characters remain, clobber them,
302
		 * and reopen the line to get the display exact.
303
		 */
304
		if (state != HARDOPEN) {
305
			DEPTH(vcline) = 0;
306
			savedoomed = doomed;
307
			if (doomed > 0) {
308
				register int cind = cindent();
309
 
310
				physdc(cind, cind + doomed);
311
				doomed = 0;
312
			}
313
			i = vreopen(LINE(vcline), lineDOT(), vcline);
314
#ifdef TRACE
315
			if (trace)
316
				fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
317
#endif
318
			if (ch == 'R')
319
				doomed = savedoomed;
320
		}
321
 
322
		/*
323
		 * All done unless we are continuing on to another line.
324
		 */
325
		if (escape != '\n')
326
			break;
327
 
328
		/*
329
		 * Set up for the new line.
330
		 * First save the current line, then construct a new
331
		 * first image for the continuation line consisting
332
		 * of any new autoindent plus the pushed ahead text.
333
		 */
334
		killU();
335
		addtext(gobblebl ? " " : "\n");
336
		vsave();
337
		cnt = 1;
338
		if (value(AUTOINDENT)) {
339
#ifdef LISPCODE
340
			if (value(LISP))
341
				indent = lindent(dot + 1);
342
			else
343
#endif
344
			     if (!HADUP && vaifirst)
345
				indent = whitecnt(linebuf);
346
			vaifirst = 0;
347
			strcLIN(vpastwh(gcursor + 1));
348
			gcursor = genindent(indent);
349
			*gcursor = 0;
350
			if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
351
				gcursor = genbuf;
115 7u83 352
			CP(gcursor, linebuf);
105 7u83 353
		} else {
115 7u83 354
			CP(genbuf, gcursor + 1);
105 7u83 355
			gcursor = genbuf;
356
		}
357
 
358
		/*
359
		 * If we started out as a single line operation and are now
360
		 * turning into a multi-line change, then we had better yank
361
		 * out dot before it changes so that undo will work
362
		 * correctly later.
363
		 */
364
		if (FIXUNDO && vundkind == VCHNG) {
365
			vremote(1, yank, 0);
366
			undap1--;
367
		}
368
 
369
		/*
370
		 * Now do the append of the new line in the buffer,
371
		 * and update the display.  If slowopen
372
		 * we don't do very much.
373
		 */
374
		vdoappend(genbuf);
375
		vundkind = VMANYINS;
376
		vcline++;
377
		if (state != VISUAL)
378
			vshow(dot, NOLINE);
379
		else {
380
			i += LINE(vcline - 1);
381
			vopen(dot, i);
382
			if (value(SLOWOPEN))
383
				vscrap();
384
			else
385
				vsync1(LINE(vcline));
386
		}
387
		strcLIN(gcursor);
388
		*gcursor = 0;
389
		cursor = linebuf;
390
		vgotoCL(qcolumn(cursor - 1, genbuf));
391
	}
392
 
393
	/*
394
	 * All done with insertion, position the cursor
395
	 * and sync the screen.
396
	 */
397
	hold = oldhold;
398
	if (cursor > linebuf)
399
		cursor--;
400
	if (state != HARDOPEN)
401
		vsyncCL();
402
	else if (cursor > linebuf)
403
		back1();
404
	doomed = 0;
405
	wcursor = cursor;
406
	vmove();
108 7u83 407
/*XXX	(void)sigsetmask(oldmask); */
105 7u83 408
}
409
 
410
/*
411
 * Subroutine for vgetline to back up a single character position,
412
 * backwards around end of lines (vgoto can't hack columns which are
413
 * less than 0 in general).
414
 */
415
back1()
416
{
417
 
418
	vgoto(destline - 1, WCOLS + destcol - 1);
419
}
420
 
421
/*
422
 * Get a line into genbuf after gcursor.
423
 * Cnt limits the number of input characters
424
 * accepted and is used for handling the replace
425
 * single character command.  Aescaped is the location
426
 * where we stick a termination indicator (whether we
427
 * ended with an ESCAPE or a newline/return.
428
 *
429
 * We do erase-kill type processing here and also
430
 * are careful about the way we do this so that it is
431
 * repeatable.  (I.e. so that your kill doesn't happen,
432
 * when you repeat an insert if it was escaped with \ the
433
 * first time you did it.  commch is the command character
434
 * involved, including the prompt for readline.
435
 */
436
char *
437
vgetline(cnt, gcursor, aescaped, commch)
438
	int cnt;
439
	register char *gcursor;
440
	bool *aescaped;
441
	char commch;
442
{
443
	register int c, ch;
444
	register char *cp;
445
	int x, y, iwhite, backsl=0;
446
	char *iglobp;
447
	char cstr[2];
115 7u83 448
	int (*OO)() = Outchar;
105 7u83 449
 
450
	/*
451
	 * Clear the output state and counters
452
	 * for autoindent backwards motion (counts of ^D, etc.)
453
	 * Remember how much white space at beginning of line so
454
	 * as not to allow backspace over autoindent.
455
	 */
456
	*aescaped = 0;
457
	ogcursor = gcursor;
458
	flusho();
459
	CDCNT = 0;
460
	HADUP = 0;
461
	HADZERO = 0;
462
	gobbled = 0;
463
	iwhite = whitecnt(genbuf);
464
	iglobp = vglobp;
465
 
466
	/*
467
	 * Carefully avoid using vinschar in the echo area.
468
	 */
469
	if (splitw)
470
		Outchar = vputchar;
471
	else {
472
		Outchar = vinschar;
473
		vprepins();
474
	}
475
	for (;;) {
476
		backsl = 0;
477
		if (gobblebl)
478
			gobblebl--;
479
		if (cnt != 0) {
480
			cnt--;
481
			if (cnt == 0)
482
				goto vadone;
483
		}
484
		c = getkey();
485
		if (c != ATTN)
486
			c &= (QUOTE|TRIM);
487
		ch = c;
488
		maphopcnt = 0;
489
		if (vglobp == 0 && Peekkey == 0 && commch != 'r')
490
			while ((ch = map(c, immacs)) != c) {
491
				c = ch;
492
				if (!value(REMAP))
493
					break;
494
				if (++maphopcnt > 256)
495
					error("Infinite macro loop");
496
			}
497
		if (!iglobp) {
498
 
499
			/*
500
			 * Erase-kill type processing.
501
			 * Only happens if we were not reading
502
			 * from untyped input when we started.
503
			 * Map users erase to ^H, kill to -1 for switch.
504
			 */
505
#ifndef USG3TTY
506
			if (c == tty.sg_erase)
507
				c = CTRL('h');
508
			else if (c == tty.sg_kill)
509
				c = -1;
510
#else
511
			if (c == tty.c_cc[VERASE])
512
				c = CTRL('h');
513
			else if (c == tty.c_cc[VKILL])
514
				c = -1;
515
#endif
516
			switch (c) {
517
 
518
			/*
519
			 * ^?		Interrupt drops you back to visual
520
			 *		command mode with an unread interrupt
521
			 *		still in the input buffer.
522
			 *
523
			 * ^\		Quit does the same as interrupt.
524
			 *		If you are a ex command rather than
525
			 *		a vi command this will drop you
526
			 *		back to command mode for sure.
527
			 */
528
			case ATTN:
529
			case QUIT:
530
				ungetkey(c);
531
				goto vadone;
532
 
533
			/*
534
			 * ^H		Backs up a character in the input.
535
			 *
536
			 * BUG:		Can't back around line boundaries.
537
			 *		This is hard because stuff has
538
			 *		already been saved for repeat.
539
			 */
540
			case CTRL('h'):
541
bakchar:
542
				cp = gcursor - 1;
543
				if (cp < ogcursor) {
544
					if (splitw) {
545
						/*
546
						 * Backspacing over readecho
547
						 * prompt. Pretend delete but
548
						 * don't beep.
549
						 */
550
						ungetkey(c);
551
						goto vadone;
552
					}
553
					beep();
554
					continue;
555
				}
556
				goto vbackup;
557
 
558
			/*
559
			 * ^W		Back up a white/non-white word.
560
			 */
561
			case CTRL('w'):
562
				wdkind = 1;
563
				for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
564
					continue;
565
				for (c = wordch(cp - 1);
566
				    cp > ogcursor && wordof(c, cp - 1); cp--)
567
					continue;
568
				goto vbackup;
569
 
570
			/*
571
			 * users kill	Kill input on this line, back to
572
			 *		the autoindent.
573
			 */
574
			case -1:
575
				cp = ogcursor;
576
vbackup:
577
				if (cp == gcursor) {
578
					beep();
579
					continue;
580
				}
581
				endim();
582
				*cp = 0;
583
				c = cindent();
584
				vgotoCL(qcolumn(cursor - 1, genbuf));
585
				if (doomed >= 0)
586
					doomed += c - cindent();
587
				gcursor = cp;
588
				continue;
589
 
590
			/*
591
			 * \		Followed by erase or kill
592
			 *		maps to just the erase or kill.
593
			 */
594
			case '\\':
595
				x = destcol, y = destline;
596
				putchar('\\');
597
				vcsync();
598
				c = getkey();
599
#ifndef USG3TTY
600
				if (c == tty.sg_erase || c == tty.sg_kill)
601
#else
602
				if (c == tty.c_cc[VERASE]
603
				    || c == tty.c_cc[VKILL])
604
#endif
605
				{
606
					vgoto(y, x);
607
					if (doomed >= 0)
608
						doomed++;
609
					goto def;
610
				}
611
				ungetkey(c), c = '\\';
612
				backsl = 1;
613
				break;
614
 
615
			/*
616
			 * ^Q		Super quote following character
617
			 *		Only ^@ is verboten (trapped at
618
			 *		a lower level) and \n forces a line
619
			 *		split so doesn't really go in.
620
			 *
621
			 * ^V		Synonym for ^Q
622
			 */
623
			case CTRL('q'):
624
			case CTRL('v'):
625
				x = destcol, y = destline;
626
				putchar('^');
627
				vgoto(y, x);
628
				c = getkey();
629
#ifdef TIOCSETC
630
				if (c == ATTN)
631
					c = nttyc.t_intrc;
632
#endif
633
				if (c != NL) {
634
					if (doomed >= 0)
635
						doomed++;
636
					goto def;
637
				}
638
				break;
639
			}
640
		}
641
 
642
		/*
643
		 * If we get a blank not in the echo area
644
		 * consider splitting the window in the wrapmargin.
645
		 */
646
		if (c != NL && !splitw) {
647
			if (c == ' ' && gobblebl) {
648
				gobbled = 1;
649
				continue;
650
			}
651
			if (value(WRAPMARGIN) &&
652
				(outcol >= OCOLUMNS - value(WRAPMARGIN) ||
653
				 backsl && outcol==0) &&
654
				commch != 'r') {
655
				/*
656
				 * At end of word and hit wrapmargin.
657
				 * Move the word to next line and keep going.
658
				 */
659
				wdkind = 1;
660
				*gcursor++ = c;
661
				if (backsl)
662
					*gcursor++ = getkey();
663
				*gcursor = 0;
664
				/*
665
				 * Find end of previous word if we are past it.
666
				 */
667
				for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--)
668
					;
669
				if (outcol+(backsl?OCOLUMNS:0) - (gcursor-cp) >= OCOLUMNS - value(WRAPMARGIN)) {
670
					/*
671
					 * Find beginning of previous word.
672
					 */
673
					for (; cp>ogcursor && !isspace(cp[-1]); cp--)
674
						;
675
					if (cp <= ogcursor) {
676
						/*
677
						 * There is a single word that
678
						 * is too long to fit.  Just
679
						 * let it pass, but beep for
680
						 * each new letter to warn
681
						 * the luser.
682
						 */
683
						c = *--gcursor;
684
						*gcursor = 0;
685
						beep();
686
						goto dontbreak;
687
					}
688
					/*
689
					 * Save it for next line.
690
					 */
691
					macpush(cp, 0);
692
					cp--;
693
				}
694
				macpush("\n", 0);
695
				/*
696
				 * Erase white space before the word.
697
				 */
698
				while (cp > ogcursor && isspace(cp[-1]))
699
					cp--;	/* skip blank */
700
				gobblebl = 3;
701
				goto vbackup;
702
			}
703
		dontbreak:;
704
		}
705
 
706
		/*
707
		 * Word abbreviation mode.
708
		 */
709
		cstr[0] = c;
710
		if (anyabbrs && gcursor > ogcursor && !wordch(cstr) && wordch(gcursor-1)) {
711
				int wdtype, abno;
712
 
713
				cstr[1] = 0;
714
				wdkind = 1;
715
				cp = gcursor - 1;
716
				for (wdtype = wordch(cp - 1);
717
				    cp > ogcursor && wordof(wdtype, cp - 1); cp--)
718
					;
719
				*gcursor = 0;
720
				for (abno=0; abbrevs[abno].mapto; abno++) {
721
					if (eq(cp, abbrevs[abno].cap)) {
722
						macpush(cstr, 0);
723
						macpush(abbrevs[abno].mapto);
724
						goto vbackup;
725
					}
726
				}
727
		}
728
 
729
		switch (c) {
730
 
731
		/*
732
		 * ^M		Except in repeat maps to \n.
733
		 */
734
		case CR:
735
			if (vglobp)
736
				goto def;
737
			c = '\n';
738
			/* presto chango ... */
739
 
740
		/*
741
		 * \n		Start new line.
742
		 */
743
		case NL:
744
			*aescaped = c;
745
			goto vadone;
746
 
747
		/*
748
		 * escape	End insert unless repeat and more to repeat.
749
		 */
750
		case ESCAPE:
751
			if (lastvgk)
752
				goto def;
753
			goto vadone;
754
 
755
		/*
756
		 * ^D		Backtab.
757
		 * ^T		Software forward tab.
758
		 *
759
		 *		Unless in repeat where this means these
760
		 *		were superquoted in.
761
		 */
762
		case CTRL('d'):
763
		case CTRL('t'):
764
			if (vglobp)
765
				goto def;
766
			/* fall into ... */
767
 
768
		/*
769
		 * ^D|QUOTE	Is a backtab (in a repeated command).
770
		 */
771
		case CTRL('d') | QUOTE:
772
			*gcursor = 0;
773
			cp = vpastwh(genbuf);
774
			c = whitecnt(genbuf);
775
			if (ch == CTRL('t')) {
776
				/*
777
				 * ^t just generates new indent replacing
778
				 * current white space rounded up to soft
779
				 * tab stop increment.
780
				 */
781
				if (cp != gcursor)
782
					/*
783
					 * BUG:		Don't hack ^T except
784
					 *		right after initial
785
					 *		white space.
786
					 */
787
					continue;
788
				cp = genindent(iwhite = backtab(c + value(SHIFTWIDTH) + 1));
789
				ogcursor = cp;
790
				goto vbackup;
791
			}
792
			/*
793
			 * ^D works only if we are at the (end of) the
794
			 * generated autoindent.  We count the ^D for repeat
795
			 * purposes.
796
			 */
797
			if (c == iwhite && c != 0)
798
				if (cp == gcursor) {
799
					iwhite = backtab(c);
800
					CDCNT++;
801
					ogcursor = cp = genindent(iwhite);
802
					goto vbackup;
803
				} else if (&cp[1] == gcursor &&
804
				    (*cp == '^' || *cp == '0')) {
805
					/*
806
					 * ^^D moves to margin, then back
807
					 * to current indent on next line.
808
					 *
809
					 * 0^D moves to margin and then
810
					 * stays there.
811
					 */
812
					HADZERO = *cp == '0';
813
					ogcursor = cp = genbuf;
814
					HADUP = 1 - HADZERO;
815
					CDCNT = 1;
816
					endim();
817
					back1();
818
					vputchar(' ');
819
					goto vbackup;
820
				}
821
			if (vglobp && vglobp - iglobp >= 2 &&
822
			    (vglobp[-2] == '^' || vglobp[-2] == '0')
823
			    && gcursor == ogcursor + 1)
824
				goto bakchar;
825
			continue;
826
 
827
		default:
828
			/*
829
			 * Possibly discard control inputs.
830
			 */
831
			if (!vglobp && junk(c)) {
832
				beep();
833
				continue;
834
			}
835
def:
836
			if (!backsl) {
837
				int cnt;
838
				putchar(c);
839
				flush();
840
			}
841
			if (gcursor > &genbuf[LBSIZE - 2])
842
				error("Line too long");
843
#ifndef	ISO
844
			*gcursor++ = c & TRIM;
845
#else
846
			if (niso(c))
847
				*gcursor++ = c & TRIM;
848
			else
849
				*gcursor++ = c;
850
#endif
851
			vcsync();
852
			if (value(SHOWMATCH) && !iglobp)
853
				if (c == ')' || c == '}')
854
					lsmatch(gcursor);
855
			continue;
856
		}
857
	}
858
vadone:
859
	*gcursor = 0;
860
	if (Outchar != termchar)
861
		Outchar = OO;
862
	endim();
863
	return (gcursor);
864
}
865
 
866
int	vgetsplit();
867
char	*vsplitpt;
868
 
869
/*
870
 * Append the line in buffer at lp
871
 * to the buffer after dot.
872
 */
873
vdoappend(lp)
874
	char *lp;
875
{
876
	register int oing = inglobal;
877
 
878
	vsplitpt = lp;
879
	inglobal = 1;
880
	ignore(append(vgetsplit, dot));
881
	inglobal = oing;
882
}
883
 
884
/*
885
 * Subroutine for vdoappend to pass to append.
886
 */
887
vgetsplit()
888
{
889
 
890
	if (vsplitpt == 0)
891
		return (EOF);
892
	strcLIN(vsplitpt);
893
	vsplitpt = 0;
894
	return (0);
895
}
896
 
897
/*
898
 * Vmaxrep determines the maximum repetitition factor
899
 * allowed that will yield total line length less than
900
 * LBSIZE characters and also does hacks for the R command.
901
 */
902
vmaxrep(ch, cnt)
903
	char ch;
904
	register int cnt;
905
{
906
	register int len, replen;
907
 
908
	if (cnt > LBSIZE - 2)
909
		cnt = LBSIZE - 2;
910
	replen = strlen(genbuf);
911
	if (ch == 'R') {
912
		len = strlen(cursor);
913
		if (replen < len)
914
			len = replen;
115 7u83 915
		CP(cursor, cursor + len);
105 7u83 916
		vUD2 += len;
917
	}
918
	len = strlen(linebuf);
919
	if (len + cnt * replen <= LBSIZE - 2)
920
		return (cnt);
921
	cnt = (LBSIZE - 2 - len) / replen;
922
	if (cnt == 0) {
923
		vsave();
924
		error("Line too long");
925
	}
926
	return (cnt);
927
}