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