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