Subversion Repositories planix.SVN

Rev

Rev 115 | 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_vops.c	7.7 (Berkeley) 6/7/85";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_tty.h"
13
#include "ex_vis.h"
14
 
15
/*
16
 * This file defines the operation sequences which interface the
17
 * logical changes to the file buffer with the internal and external
18
 * display representations.
19
 */
20
 
21
/*
22
 * Undo.
23
 *
24
 * Undo is accomplished in two ways.  We often for small changes in the
25
 * current line know how (in terms of a change operator) how the change
26
 * occurred.  Thus on an intelligent terminal we can undo the operation
27
 * by another such operation, using insert and delete character
28
 * stuff.  The pointers vU[AD][12] index the buffer vutmp when this
29
 * is possible and provide the necessary information.
30
 *
31
 * The other case is that the change involved multiple lines or that
32
 * we have moved away from the line or forgotten how the change was
33
 * accomplished.  In this case we do a redisplay and hope that the
34
 * low level optimization routines (which don't look for winning
35
 * via insert/delete character) will not lose too badly.
36
 */
37
char	*vUA1, *vUA2;
38
char	*vUD1, *vUD2;
39
 
40
vUndo()
41
{
42
 
43
	/*
44
	 * Avoid UU which clobbers ability to do u.
45
	 */
46
	if (vundkind == VCAPU || vUNDdot != dot) {
47
		beep();
48
		return;
49
	}
50
#ifndef	BIT8
115 7u83 51
	CP(vutmp, linebuf);
105 7u83 52
#else
53
	sc_strcpy(vutmp, linebuf);
54
#endif
55
	vUD1 = linebuf; vUD2 = strend(linebuf);
56
	putmk1(dot, vUNDsav);
57
	getDOT();
58
	vUA1 = linebuf; vUA2 = strend(linebuf);
59
	vundkind = VCAPU;
60
	if (state == ONEOPEN || state == HARDOPEN) {
61
		vjumpto(dot, vUNDcurs, 0);
62
		return;
63
	}
64
	vdirty(vcline, 1);
65
	vsyncCL();
66
	cursor = linebuf;
67
	vfixcurs();
68
}
69
 
70
vundo(show)
71
bool show;	/* if true update the screen */
72
{
73
	register int cnt;
74
	register line *addr;
75
	register char *cp;
76
	char temp[LBSIZE];
77
	bool savenote;
115 7u83 78
	int (*OO)();
105 7u83 79
	short oldhold = hold;
80
 
81
	switch (vundkind) {
82
 
83
	case VMANYINS:
84
		wcursor = 0;
85
		addr1 = undap1;
86
		addr2 = undap2 - 1;
87
		vsave();
88
		YANKreg('1');
89
		notecnt = 0;
90
		/* fall into ... */
91
 
92
	case VMANY:
93
	case VMCHNG:
94
		vsave();
95
		addr = dot - vcline;
96
		notecnt = 1;
97
		if (undkind == UNDPUT && undap1 == undap2) {
98
			beep();
99
			break;
100
		}
101
		/*
102
		 * Undo() call below basically replaces undap1 to undap2-1
103
		 * with dol through unddol-1.  Hack screen image to
104
		 * reflect this replacement.
105
		 */
106
		if (show)
107
			if (undkind == UNDMOVE)
108
				vdirty(0, LINES);
109
			else
110
				vreplace(undap1 - addr, undap2 - undap1,
111
				    undkind == UNDPUT ? 0 : unddol - dol);
112
		savenote = notecnt;
113
		undo(1);
114
		if (show && (vundkind != VMCHNG || addr != dot))
115
			killU();
116
		vundkind = VMANY;
117
		cnt = dot - addr;
118
		if (cnt < 0 || cnt > vcnt || state != VISUAL) {
119
			if (show)
120
				vjumpto(dot, NOSTR, '.');
121
			break;
122
		}
123
		if (!savenote)
124
			notecnt = 0;
125
		if (show) {
126
			vcline = cnt;
127
			vrepaint(vmcurs);
128
		}
129
		vmcurs = 0;
130
		break;
131
 
132
	case VCHNG:
133
	case VCAPU:
134
		vundkind = VCHNG;
135
#ifndef	BIT8
136
		strcpy(temp, vutmp);
137
		strcpy(vutmp, linebuf);
138
#else
139
		cs_strcpy(temp, vutmp);
140
		sc_strcpy(vutmp, linebuf);
141
#endif
142
		doomed = column(vUA2 - 1) - column(vUA1 - 1);
143
		strcLIN(temp);
144
		cp = vUA1; vUA1 = vUD1; vUD1 = cp;
145
		cp = vUA2; vUA2 = vUD2; vUD2 = cp;
146
		if (!show)
147
			break;
148
		cursor = vUD1;
149
		if (state == HARDOPEN) {
150
			doomed = 0;
151
			vsave();
152
			vopen(dot, WBOT);
153
			vnline(cursor);
154
			break;
155
		}
156
		/*
157
		 * Pseudo insert command.
158
		 */
159
		vcursat(cursor);
115 7u83 160
		OO = Outchar; Outchar = vinschar; hold |= HOLDQIK;
105 7u83 161
		vprepins();
162
		temp[vUA2 - linebuf] = 0;
163
		for (cp = &temp[vUA1 - linebuf]; *cp;)
164
			putchar(*cp++);
165
		Outchar = OO; hold = oldhold;
166
		endim();
167
		physdc(cindent(), cindent() + doomed);
168
		doomed = 0;
169
		vdirty(vcline, 1);
170
		vsyncCL();
171
		if (cursor > linebuf && cursor >= strend(linebuf))
172
			cursor--;
173
		vfixcurs();
174
		break;
175
 
176
	case VNONE:
177
		beep();
178
		break;
179
	}
180
}
181
 
182
/*
183
 * Routine to handle a change inside a macro.
184
 * Fromvis is true if we were called from a visual command (as
185
 * opposed to an ex command).  This has nothing to do with being
186
 * in open/visual mode as :s/foo/bar is not fromvis.
187
 */
188
vmacchng(fromvis)
189
bool fromvis;
190
{
191
	line *savedot, *savedol;
192
	char *savecursor;
193
	char savelb[LBSIZE];
194
	int nlines, more;
195
	register line *a1, *a2;
196
	char ch;	/* DEBUG */
197
	int copyw(), copywR();
198
 
199
	if (!inopen)
200
		return;
201
	if (!vmacp)
202
		vch_mac = VC_NOTINMAC;
203
#ifdef TRACE
204
	if (trace)
205
		fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
206
#endif
207
	if (vmacp && fromvis)
208
		vsave();
209
#ifdef TRACE
210
	if (trace)
211
		fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
212
#endif
213
	switch(vch_mac) {
214
	case VC_NOCHANGE:
215
		vch_mac = VC_ONECHANGE;
216
		break;
217
	case VC_ONECHANGE:
218
		/* Save current state somewhere */
219
#ifdef TRACE
220
		vudump("before vmacchng hairy case");
221
#endif
222
		savedot = dot; savedol = dol; savecursor = cursor;
115 7u83 223
		CP(savelb, linebuf);
105 7u83 224
		nlines = dol - zero;
225
		while ((line *) endcore - truedol < nlines)
226
			morelines();
227
		copyw(truedol+1, zero+1, nlines);
228
		truedol += nlines;
229
 
230
#ifdef TRACE
231
		visdump("before vundo");
232
#endif
233
		/* Restore state as it was at beginning of macro */
234
		vundo(0);
235
#ifdef TRACE
236
		visdump("after vundo");
237
		vudump("after vundo");
238
#endif
239
 
240
		/* Do the saveall we should have done then */
241
		saveall();
242
#ifdef TRACE
243
		vudump("after saveall");
244
#endif
245
 
246
		/* Restore current state from where saved */
247
		more = savedol - dol; /* amount we shift everything by */
248
		if (more)
249
			(*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
250
		unddol += more; truedol += more; undap2 += more;
251
 
252
		truedol -= nlines;
253
		copyw(zero+1, truedol+1, nlines);
254
		dot = savedot; dol = savedol ; cursor = savecursor;
115 7u83 255
		CP(linebuf, savelb);
105 7u83 256
		vch_mac = VC_MANYCHANGE;
257
 
258
		/* Arrange that no further undo saving happens within macro */
259
		otchng = tchng;	/* Copied this line blindly - bug? */
260
		inopen = -1;	/* no need to save since it had to be 1 or -1 before */
261
		vundkind = VMANY;
262
#ifdef TRACE
263
		vudump("after vmacchng");
264
#endif
265
		break;
266
	case VC_NOTINMAC:
267
	case VC_MANYCHANGE:
268
		/* Nothing to do for various reasons. */
269
		break;
270
	}
271
}
272
 
273
/*
274
 * Initialize undo information before an append.
275
 */
276
vnoapp()
277
{
278
 
279
	vUD1 = vUD2 = cursor;
280
}
281
 
282
/*
283
 * All the rest of the motion sequences have one or more
284
 * cases to deal with.  In the case wdot == 0, operation
285
 * is totally within current line, from cursor to wcursor.
286
 * If wdot is given, but wcursor is 0, then operation affects
287
 * the inclusive line range.  The hardest case is when both wdot
288
 * and wcursor are given, then operation affects from line dot at
289
 * cursor to line wdot at wcursor.
290
 */
291
 
292
/*
293
 * Move is simple, except for moving onto new lines in hardcopy open mode.
294
 */
295
vmove()
296
{
297
	register int cnt;
298
 
299
	if (wdot) {
300
		if (wdot < one || wdot > dol) {
301
			beep();
302
			return;
303
		}
304
		cnt = wdot - dot;
305
		wdot = NOLINE;
306
		if (cnt)
307
			killU();
308
		vupdown(cnt, wcursor);
309
		return;
310
	}
311
 
312
	/*
313
	 * When we move onto a new line, save information for U undo.
314
	 */
315
	if (vUNDdot != dot) {
316
		vUNDsav = *dot;
317
		vUNDcurs = wcursor;
318
		vUNDdot = dot;
319
	}
320
 
321
	/*
322
	 * In hardcopy open, type characters to left of cursor
323
	 * on new line, or back cursor up if its to left of where we are.
324
	 * In any case if the current line is ``rubbled'' i.e. has trashy
325
	 * looking overstrikes on it or \'s from deletes, we reprint
326
	 * so it is more comprehensible (and also because we can't work
327
	 * if we let it get more out of sync since column() won't work right.
328
	 */
329
	if (state == HARDOPEN) {
330
		register char *cp;
331
		if (rubble) {
332
			register int c;
333
			int oldhold = hold;
334
 
335
			sethard();
336
			cp = wcursor;
337
			c = *cp;
338
			*cp = 0;
339
			hold |= HOLDDOL;
340
			vreopen(WTOP, lineDOT(), vcline);
341
			hold = oldhold;
342
			*cp = c;
343
		} else if (wcursor > cursor) {
344
			vfixcurs();
345
			for (cp = cursor; *cp && cp < wcursor;) {
346
#ifndef	ISO
347
				register int c = *cp++ & TRIM;
348
#else
349
				register int c;
350
 
351
				if (niso(*cp))
352
					c = *cp++ & TRIM;
353
				else
354
					c = *cp++;
355
#endif
356
 
357
				putchar(c ? c : ' ');
358
			}
359
		}
360
	}
361
	vsetcurs(wcursor);
362
}
363
 
364
/*
365
 * Delete operator.
366
 *
367
 * Hard case of deleting a range where both wcursor and wdot
368
 * are specified is treated as a special case of change and handled
369
 * by vchange (although vchange may pass it back if it degenerates
370
 * to a full line range delete.)
371
 */
372
vdelete(c)
373
	char c;
374
{
375
	register char *cp;
376
	register int i;
377
 
378
	if (wdot) {
379
		if (wcursor) {
380
			vchange('d');
381
			return;
382
		}
383
		if ((i = xdw()) < 0)
384
			return;
385
		if (state != VISUAL) {
386
			vgoto(LINE(0), 0);
387
			vputchar('@');
388
		}
389
		wdot = dot;
390
		vremote(i, delete, 0);
391
		notenam = "delete";
392
		DEL[0] = 0;
393
		killU();
394
		vreplace(vcline, i, 0);
395
		if (wdot > dol)
396
			vcline--;
397
		vrepaint(NOSTR);
398
		return;
399
	}
400
	if (wcursor < linebuf)
401
		wcursor = linebuf;
402
	if (cursor == wcursor) {
403
		beep();
404
		return;
405
	}
406
	i = vdcMID();
407
	cp = cursor;
408
	setDEL();
115 7u83 409
	CP(cp, wcursor);
105 7u83 410
	if (cp > linebuf && (cp[0] == 0 || c == '#'))
411
		cp--;
412
	if (state == HARDOPEN) {
413
		bleep(i, cp);
414
		cursor = cp;
415
		return;
416
	}
417
	physdc(column(cursor - 1), i);
418
	DEPTH(vcline) = 0;
419
	vreopen(LINE(vcline), lineDOT(), vcline);
420
	vsyncCL();
421
	vsetcurs(cp);
422
}
423
 
424
/*
425
 * Change operator.
426
 *
427
 * In a single line we mark the end of the changed area with '$'.
428
 * On multiple whole lines, we clear the lines first.
429
 * Across lines with both wcursor and wdot given, we delete
430
 * and sync then append (but one operation for undo).
431
 */
432
vchange(c)
433
	char c;
434
{
435
	register char *cp;
436
	register int i, ind, cnt;
437
	line *addr;
438
 
439
	if (wdot) {
440
		/*
441
		 * Change/delete of lines or across line boundaries.
442
		 */
443
		if ((cnt = xdw()) < 0)
444
			return;
445
		getDOT();
446
		if (wcursor && cnt == 1) {
447
			/*
448
			 * Not really.
449
			 */
450
			wdot = 0;
451
			if (c == 'd') {
452
				vdelete(c);
453
				return;
454
			}
455
			goto smallchange;
456
		}
457
		if (cursor && wcursor) {
458
			/*
459
			 * Across line boundaries, but not
460
			 * necessarily whole lines.
461
			 * Construct what will be left.
462
			 */
463
			*cursor = 0;
464
			strcpy(genbuf, linebuf);
118 7u83 465
			ex_getline(*wdot);
105 7u83 466
			if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) {
467
				getDOT();
468
				beep();
469
				return;
470
			}
471
			strcat(genbuf, wcursor);
472
			if (c == 'd' && *vpastwh(genbuf) == 0) {
473
				/*
474
				 * Although this is a delete
475
				 * spanning line boundaries, what
476
				 * would be left is all white space,
477
				 * so take it all away.
478
				 */
479
				wcursor = 0;
480
				getDOT();
481
				op = 0;
482
				notpart(lastreg);
483
				notpart('1');
484
				vdelete(c);
485
				return;
486
			}
487
			ind = -1;
488
		} else if (c == 'd' && wcursor == 0) {
489
			vdelete(c);
490
			return;
491
		} else
492
#ifdef LISPCODE
493
			/*
494
			 * We are just substituting text for whole lines,
495
			 * so determine the first autoindent.
496
			 */
497
			if (value(LISP) && value(AUTOINDENT))
498
				ind = lindent(dot);
499
			else
500
#endif
501
				ind = whitecnt(linebuf);
502
		i = vcline >= 0 ? LINE(vcline) : WTOP;
503
 
504
		/*
505
		 * Delete the lines from the buffer,
506
		 * and remember how the partial stuff came about in
507
		 * case we are told to put.
508
		 */
509
		addr = dot;
510
		vremote(cnt, delete, 0);
511
		setpk();
512
		notenam = "delete";
513
		if (c != 'd')
514
			notenam = "change";
515
		/*
516
		 * If DEL[0] were nonzero, put would put it back
517
		 * rather than the deleted lines.
518
		 */
519
		DEL[0] = 0;
520
		if (cnt > 1)
521
			killU();
522
 
523
		/*
524
		 * Now hack the screen image coordination.
525
		 */
526
		vreplace(vcline, cnt, 0);
527
		wdot = NOLINE;
528
		noteit(0);
529
		vcline--;
530
		if (addr <= dol)
531
			dot--;
532
 
533
		/*
534
		 * If this is a across line delete/change,
535
		 * cursor stays where it is; just splice together the pieces
536
		 * of the new line.  Otherwise generate a autoindent
537
		 * after a S command.
538
		 */
539
		if (ind >= 0) {
540
			*genindent(ind) = 0;
541
			vdoappend(genbuf);
542
		} else {
543
			vmcurs = cursor;
544
			strcLIN(genbuf);
545
			vdoappend(linebuf);
546
		}
547
 
548
		/*
549
		 * Indicate a change on hardcopies by
550
		 * erasing the current line.
551
		 */
552
		if (c != 'd' && state != VISUAL && state != HARDOPEN) {
553
			int oldhold = hold;
554
 
555
			hold |= HOLDAT, vclrlin(i, dot), hold = oldhold;
556
		}
557
 
558
		/*
559
		 * Open the line (logically) on the screen, and 
560
		 * update the screen tail.  Unless we are really a delete
561
		 * go off and gather up inserted characters.
562
		 */
563
		vcline++;
564
		if (vcline < 0)
565
			vcline = 0;
566
		vopen(dot, i);
567
		vsyncCL();
568
		noteit(1);
569
		if (c != 'd') {
570
			if (ind >= 0) {
571
				cursor = linebuf;
572
				linebuf[0] = 0;
573
				vfixcurs();
574
			} else {
575
				ind = 0;
576
				vcursat(cursor);
577
			}
578
			vappend('x', 1, ind);
579
			return;
580
		}
581
		if (*cursor == 0 && cursor > linebuf)
582
			cursor--;
583
		vrepaint(cursor);
584
		return;
585
	}
586
 
587
smallchange:
588
	/*
589
	 * The rest of this is just low level hacking on changes
590
	 * of small numbers of characters.
591
	 */
592
	if (wcursor < linebuf)
593
		wcursor = linebuf;
594
	if (cursor == wcursor) {
595
		beep();
596
		return;
597
	}
598
	i = vdcMID();
599
	cp = cursor;
600
	if (state != HARDOPEN)
601
		vfixcurs();
602
 
603
	/*
604
	 * Put out the \\'s indicating changed text in hardcopy,
605
	 * or mark the end of the change with $ if not hardcopy.
606
	 */
607
	if (state == HARDOPEN) 
608
		bleep(i, cp);
609
	else {
610
		vcursbef(wcursor);
611
		putchar('$');
612
		i = cindent();
613
	}
614
 
615
	/*
616
	 * Remember the deleted text for possible put,
617
	 * and then prepare and execute the input portion of the change.
618
	 */
619
	cursor = cp;
620
	setDEL();
115 7u83 621
	CP(cursor, wcursor);
105 7u83 622
	if (state != HARDOPEN) {
623
		vcursaft(cursor - 1);
624
		doomed = i - cindent();
625
	} else {
626
/*
627
		sethard();
628
		wcursor = cursor;
629
		cursor = linebuf;
630
		vgoto(outline, value(NUMBER) << 3);
631
		vmove();
632
*/
633
		doomed = 0;
634
	}
635
	prepapp();
636
	vappend('c', 1, 0);
637
}
638
 
639
/*
640
 * Open new lines.
641
 *
642
 * Tricky thing here is slowopen.  This causes display updating
643
 * to be held off so that 300 baud dumb terminals don't lose badly.
644
 * This also suppressed counts, which otherwise say how many blank
645
 * space to open up.  Counts are also suppressed on intelligent terminals.
646
 * Actually counts are obsoleted, since if your terminal is slow
647
 * you are better off with slowopen.
648
 */
649
voOpen(c, cnt)
650
	int c;	/* mjm: char --> int */
651
	register int cnt;
652
{
653
	register int ind = 0, i;
654
	short oldhold = hold;
655
	long oldmask;
656
 
657
	if (value(SLOWOPEN) || value(REDRAW) && AL && DL)
658
		cnt = 1;
107 7u83 659
/* XXX	oldmask = sigblock(sigmask(SIGWINCH)); */
105 7u83 660
	vsave();
661
	setLAST();
662
	if (value(AUTOINDENT))
663
		ind = whitecnt(linebuf);
664
	if (c == 'O') {
665
		vcline--;
666
		dot--;
667
		if (dot > zero)
668
			getDOT();
669
	}
670
	if (value(AUTOINDENT)) {
671
#ifdef LISPCODE
672
		if (value(LISP))
673
			ind = lindent(dot + 1);
674
#endif
675
	}
676
	killU();
677
	prepapp();
678
	if (FIXUNDO)
679
		vundkind = VMANY;
680
	if (state != VISUAL)
681
		c = WBOT + 1;
682
	else {
683
		c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
684
		if (c < ZERO)
685
			c = ZERO;
686
		i = LINE(vcline + 1) - c;
687
		if (i < cnt && c <= WBOT && (!AL || !DL))
688
			vinslin(c, cnt - i, vcline);
689
	}
690
	*genindent(ind) = 0;
691
	vdoappend(genbuf);
692
	vcline++;
693
	oldhold = hold;
694
	hold |= HOLDROL;
695
	vopen(dot, c);
696
	hold = oldhold;
697
	if (value(SLOWOPEN))
698
		/*
699
		 * Oh, so lazy!
700
		 */
701
		vscrap();
702
	else
703
		vsync1(LINE(vcline));
704
	cursor = linebuf;
705
	linebuf[0] = 0;
706
	vappend('o', 1, ind);
108 7u83 707
/*XXX	(void)sigsetmask(oldmask); XXX*/
105 7u83 708
}
709
 
710
/*
711
 * > < and = shift operators.
712
 *
713
 * Note that =, which aligns lisp, is just a ragged sort of shift,
714
 * since it never distributes text between lines.
715
 */
716
char	vshnam[2] = { 'x', 0 };
717
 
718
vshftop()
719
{
720
	register line *addr;
721
	register int cnt;
722
 
723
	if ((cnt = xdw()) < 0)
724
		return;
725
	addr = dot;
726
	vremote(cnt, vshift, 0);
727
	vshnam[0] = op;
728
	notenam = vshnam;
729
	dot = addr;
730
	vreplace(vcline, cnt, cnt);
731
	if (state == HARDOPEN)
732
		vcnt = 0;
733
	vrepaint(NOSTR);
734
}
735
 
736
/*
737
 * !.
738
 *
739
 * Filter portions of the buffer through unix commands.
740
 */
741
vfilter()
742
{
743
	register line *addr;
744
	register int cnt;
745
	char *oglobp;
746
	short d;
747
 
748
	if ((cnt = xdw()) < 0)
749
		return;
750
	if (vglobp)
751
		vglobp = uxb;
752
	if (readecho('!'))
753
		return;
754
	oglobp = globp; globp = genbuf + 1;
755
	d = peekc; ungetchar(0);
756
	CATCH
757
		fixech();
758
		unix0(0);
759
	ONERR
760
		splitw = 0;
761
		ungetchar(d);
762
		vrepaint(cursor);
763
		globp = oglobp;
764
		return;
765
	ENDCATCH
766
	ungetchar(d); globp = oglobp;
767
	addr = dot;
768
	CATCH
769
		vgoto(WECHO, 0); flusho();
770
		vremote(cnt, filter, 2);
771
	ONERR
772
		vdirty(0, LINES);
773
	ENDCATCH
774
	if (dot == zero && dol > zero)
775
		dot = one;
776
	splitw = 0;
777
	notenam = "";
778
	/*
779
	 * BUG: we shouldn't be depending on what undap2 and undap1 are,
780
	 * since we may be inside a macro.  What's really wanted is the
781
	 * number of lines we read from the filter.  However, the mistake
782
	 * will be an overestimate so it only results in extra work,
783
	 * it shouldn't cause any real screwups.
784
	 */
785
	vreplace(vcline, cnt, undap2 - undap1);
786
	dot = addr;
787
	if (dot > dol) {
788
		dot--;
789
		vcline--;
790
	}
791
	vrepaint(NOSTR);
792
}
793
 
794
/*
795
 * Xdw exchanges dot and wdot if appropriate and also checks
796
 * that wdot is reasonable.  Its name comes from
797
 *	xchange dotand wdot
798
 */
799
xdw()
800
{
801
	register char *cp;
802
	register int cnt;
803
/*
804
	register int notp = 0;
805
 */
806
 
807
	if (wdot == NOLINE || wdot < one || wdot > dol) {
808
		beep();
809
		return (-1);
810
	}
811
	vsave();
812
	setLAST();
813
	if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) {
814
		register line *addr;
815
 
816
		vcline -= dot - wdot;
817
		addr = dot; dot = wdot; wdot = addr;
818
		cp = cursor; cursor = wcursor; wcursor = cp;
819
	}
820
	/*
821
	 * If a region is specified but wcursor is at the begining
822
	 * of the last line, then we move it to be the end of the
823
	 * previous line (actually off the end).
824
	 */
825
	if (cursor && wcursor == linebuf && wdot > dot) {
826
		wdot--;
827
		getDOT();
828
		if (vpastwh(linebuf) >= cursor)
829
			wcursor = 0;
830
		else {
118 7u83 831
			ex_getline(*wdot);
105 7u83 832
			wcursor = strend(linebuf);
833
			getDOT();
834
		}
835
		/*
836
		 * Should prepare in caller for possible dot == wdot.
837
		 */
838
	}
839
	cnt = wdot - dot + 1;
840
	if (vreg) {
841
		vremote(cnt, YANKreg, vreg);
842
/*
843
		if (notp)
844
			notpart(vreg);
845
 */
846
	}
847
 
848
	/*
849
	 * Kill buffer code.  If delete operator is c or d, then save
850
	 * the region in numbered buffers.
851
	 *
852
	 * BUG:			This may be somewhat inefficient due
853
	 *			to the way named buffer are implemented,
854
	 *			necessitating some optimization.
855
	 */
856
	vreg = 0;
857
	if (any(op, "cd")) {
858
		vremote(cnt, YANKreg, '1');
859
/*
860
		if (notp)
861
			notpart('1');
862
 */
863
	}
864
	return (cnt);
865
}
866
 
867
/*
868
 * Routine for vremote to call to implement shifts.
869
 */
870
vshift()
871
{
872
 
873
	shift(op, 1);
874
}
875
 
876
/*
877
 * Replace a single character with the next input character.
878
 * A funny kind of insert.
879
 */
880
vrep(cnt)
881
	register int cnt;
882
{
883
	register int i, c;
884
 
885
	if (cnt > strlen(cursor)) {
886
		beep();
887
		return;
888
	}
889
	i = column(cursor + cnt - 1);
890
	vcursat(cursor);
891
	doomed = i - cindent();
892
	if (!vglobp) {
893
		c = getesc();
894
		if (c == 0) {
895
			vfixcurs();
896
			return;
897
		}
898
		ungetkey(c);
899
	}
900
#ifndef	BIT8
115 7u83 901
	CP(vutmp, linebuf);
105 7u83 902
#else
903
	sc_strcpy(vutmp, linebuf);
904
#endif
905
	if (FIXUNDO)
906
		vundkind = VCHNG;
907
	wcursor = cursor + cnt;
908
	vUD1 = cursor; vUD2 = wcursor;
115 7u83 909
	CP(cursor, wcursor);
105 7u83 910
	prepapp();
911
	vappend('r', cnt, 0);
912
	*lastcp++ = INS[0];
913
	setLAST();
914
}
915
 
916
/*
917
 * Yank.
918
 *
919
 * Yanking to string registers occurs for free (essentially)
920
 * in the routine xdw().
921
 */
922
vyankit()
923
{
924
	register int cnt;
925
 
926
	if (wdot) {
927
		if ((cnt = xdw()) < 0)
928
			return;
929
		vremote(cnt, yank, 0);
930
		setpk();
931
		notenam = "yank";
932
		if (FIXUNDO)
933
			vundkind = VNONE;
934
		DEL[0] = 0;
935
		wdot = NOLINE;
936
		if (notecnt <= vcnt - vcline && notecnt < value(REPORT))
937
			notecnt = 0;
938
		vrepaint(cursor);
939
		return;
940
	}
941
	takeout(DEL);
942
}
943
 
944
/*
945
 * Set pkill variables so a put can
946
 * know how to put back partial text.
947
 * This is necessary because undo needs the complete
948
 * line images to be saved, while a put wants to trim
949
 * the first and last lines.  The compromise
950
 * is for put to be more clever.
951
 */
952
setpk()
953
{
954
 
955
	if (wcursor) {
956
		pkill[0] = cursor;
957
		pkill[1] = wcursor;
958
	}
959
}