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