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