1 /* Copyright (c) 1981 Regents of the University of California */ 2 static char *sccsid = "@(#)ex_vops.c 7.1 07/08/81"; 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 */ 29 char *vUA1, *vUA2; 30 char *vUD1, *vUD2; 31 32 vUndo() 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(); 54 cursor = linebuf; 55 vfixcurs(); 56 } 57 58 vundo(show) 59 bool show; /* if true update the screen */ 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(); 87 break; 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 */ 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); 100 savenote = notecnt; 101 undo(1); 102 if (show && (vundkind != VMCHNG || addr != dot)) 103 killU(); 104 vundkind = VMANY; 105 cnt = dot - addr; 106 if (cnt < 0 || cnt > vcnt || state != VISUAL) { 107 if (show) 108 vjumpto(dot, NOSTR, '.'); 109 break; 110 } 111 if (!savenote) 112 notecnt = 0; 113 if (show) { 114 vcline = cnt; 115 vrepaint(vmcurs); 116 } 117 vmcurs = 0; 118 break; 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; 129 if (!show) 130 break; 131 cursor = vUD1; 132 if (state == HARDOPEN) { 133 doomed = 0; 134 vsave(); 135 vopen(dot, WBOT); 136 vnline(cursor); 137 break; 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(); 157 break; 158 159 case VNONE: 160 beep(); 161 break; 162 } 163 } 164 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 */ 171 vmacchng(fromvis) 172 bool fromvis; 173 { 174 line *savedot, *savedol; 175 char *savecursor; 176 char savelb[LBSIZE]; 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; 206 CP(savelb, linebuf); 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); 233 unddol += more; truedol += more; undap2 += more; 234 235 truedol -= nlines; 236 copyw(zero+1, truedol+1, nlines); 237 dot = savedot; dol = savedol ; cursor = savecursor; 238 CP(linebuf, savelb); 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 256 /* 257 * Initialize undo information before an append. 258 */ 259 vnoapp() 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 */ 278 vmove() 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 */ 346 vdelete(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 */ 406 vchange(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 561 smallchange: 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 */ 623 voOpen(c, cnt) 624 int c; /* mjm: char --> int */ 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(); 650 if (FIXUNDO) 651 vundkind = VMANY; 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 */ 687 char vshnam[2] = { 'x', 0 }; 688 689 vshftop() 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 */ 712 vfilter() 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 = ""; 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 */ 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 */ 769 xdw() 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 */ 840 vshift() 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 */ 850 vrep(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); 871 if (FIXUNDO) 872 vundkind = VCHNG; 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 */ 888 vyankit() 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"; 898 if (FIXUNDO) 899 vundkind = VNONE; 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 */ 918 setpk() 919 { 920 921 if (wcursor) { 922 pkill[0] = cursor; 923 pkill[1] = wcursor; 924 } 925 } 926