1 /* Copyright (c) 1981 Regents of the University of California */ 2 static char *sccsid = "@(#)ex_vops.c 7.4 03/27/85"; 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 int oldmask; 630 631 if (value(SLOWOPEN) || value(REDRAW) && AL && DL) 632 cnt = 1; 633 oldmask = sigblock(sigmask(SIGWINCH)); 634 vsave(); 635 setLAST(); 636 if (value(AUTOINDENT)) 637 ind = whitecnt(linebuf); 638 if (c == 'O') { 639 vcline--; 640 dot--; 641 if (dot > zero) 642 getDOT(); 643 } 644 if (value(AUTOINDENT)) { 645 #ifdef LISPCODE 646 if (value(LISP)) 647 ind = lindent(dot + 1); 648 #endif 649 } 650 killU(); 651 prepapp(); 652 if (FIXUNDO) 653 vundkind = VMANY; 654 if (state != VISUAL) 655 c = WBOT + 1; 656 else { 657 c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); 658 if (c < ZERO) 659 c = ZERO; 660 i = LINE(vcline + 1) - c; 661 if (i < cnt && c <= WBOT && (!AL || !DL)) 662 vinslin(c, cnt - i, vcline); 663 } 664 *genindent(ind) = 0; 665 vdoappend(genbuf); 666 vcline++; 667 oldhold = hold; 668 hold |= HOLDROL; 669 vopen(dot, c); 670 hold = oldhold; 671 if (value(SLOWOPEN)) 672 /* 673 * Oh, so lazy! 674 */ 675 vscrap(); 676 else 677 vsync1(LINE(vcline)); 678 cursor = linebuf; 679 linebuf[0] = 0; 680 vappend('o', 1, ind); 681 (void)sigsetmask(oldmask); 682 } 683 684 /* 685 * > < and = shift operators. 686 * 687 * Note that =, which aligns lisp, is just a ragged sort of shift, 688 * since it never distributes text between lines. 689 */ 690 char vshnam[2] = { 'x', 0 }; 691 692 vshftop() 693 { 694 register line *addr; 695 register int cnt; 696 697 if ((cnt = xdw()) < 0) 698 return; 699 addr = dot; 700 vremote(cnt, vshift, 0); 701 vshnam[0] = op; 702 notenam = vshnam; 703 dot = addr; 704 vreplace(vcline, cnt, cnt); 705 if (state == HARDOPEN) 706 vcnt = 0; 707 vrepaint(NOSTR); 708 } 709 710 /* 711 * !. 712 * 713 * Filter portions of the buffer through unix commands. 714 */ 715 vfilter() 716 { 717 register line *addr; 718 register int cnt; 719 char *oglobp; 720 short d; 721 722 if ((cnt = xdw()) < 0) 723 return; 724 if (vglobp) 725 vglobp = uxb; 726 if (readecho('!')) 727 return; 728 oglobp = globp; globp = genbuf + 1; 729 d = peekc; ungetchar(0); 730 CATCH 731 fixech(); 732 unix0(0); 733 ONERR 734 splitw = 0; 735 ungetchar(d); 736 vrepaint(cursor); 737 globp = oglobp; 738 return; 739 ENDCATCH 740 ungetchar(d); globp = oglobp; 741 addr = dot; 742 CATCH 743 vgoto(WECHO, 0); flusho(); 744 vremote(cnt, filter, 2); 745 ONERR 746 vdirty(0, LINES); 747 ENDCATCH 748 if (dot == zero && dol > zero) 749 dot = one; 750 splitw = 0; 751 notenam = ""; 752 /* 753 * BUG: we shouldn't be depending on what undap2 and undap1 are, 754 * since we may be inside a macro. What's really wanted is the 755 * number of lines we read from the filter. However, the mistake 756 * will be an overestimate so it only results in extra work, 757 * it shouldn't cause any real screwups. 758 */ 759 vreplace(vcline, cnt, undap2 - undap1); 760 dot = addr; 761 if (dot > dol) { 762 dot--; 763 vcline--; 764 } 765 vrepaint(NOSTR); 766 } 767 768 /* 769 * Xdw exchanges dot and wdot if appropriate and also checks 770 * that wdot is reasonable. Its name comes from 771 * xchange dotand wdot 772 */ 773 xdw() 774 { 775 register char *cp; 776 register int cnt; 777 /* 778 register int notp = 0; 779 */ 780 781 if (wdot == NOLINE || wdot < one || wdot > dol) { 782 beep(); 783 return (-1); 784 } 785 vsave(); 786 setLAST(); 787 if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) { 788 register line *addr; 789 790 vcline -= dot - wdot; 791 addr = dot; dot = wdot; wdot = addr; 792 cp = cursor; cursor = wcursor; wcursor = cp; 793 } 794 /* 795 * If a region is specified but wcursor is at the begining 796 * of the last line, then we move it to be the end of the 797 * previous line (actually off the end). 798 */ 799 if (cursor && wcursor == linebuf && wdot > dot) { 800 wdot--; 801 getDOT(); 802 if (vpastwh(linebuf) >= cursor) 803 wcursor = 0; 804 else { 805 getline(*wdot); 806 wcursor = strend(linebuf); 807 getDOT(); 808 } 809 /* 810 * Should prepare in caller for possible dot == wdot. 811 */ 812 } 813 cnt = wdot - dot + 1; 814 if (vreg) { 815 vremote(cnt, YANKreg, vreg); 816 /* 817 if (notp) 818 notpart(vreg); 819 */ 820 } 821 822 /* 823 * Kill buffer code. If delete operator is c or d, then save 824 * the region in numbered buffers. 825 * 826 * BUG: This may be somewhat inefficient due 827 * to the way named buffer are implemented, 828 * necessitating some optimization. 829 */ 830 vreg = 0; 831 if (any(op, "cd")) { 832 vremote(cnt, YANKreg, '1'); 833 /* 834 if (notp) 835 notpart('1'); 836 */ 837 } 838 return (cnt); 839 } 840 841 /* 842 * Routine for vremote to call to implement shifts. 843 */ 844 vshift() 845 { 846 847 shift(op, 1); 848 } 849 850 /* 851 * Replace a single character with the next input character. 852 * A funny kind of insert. 853 */ 854 vrep(cnt) 855 register int cnt; 856 { 857 register int i, c; 858 859 if (cnt > strlen(cursor)) { 860 beep(); 861 return; 862 } 863 i = column(cursor + cnt - 1); 864 vcursat(cursor); 865 doomed = i - cindent(); 866 if (!vglobp) { 867 c = getesc(); 868 if (c == 0) { 869 vfixcurs(); 870 return; 871 } 872 ungetkey(c); 873 } 874 CP(vutmp, linebuf); 875 if (FIXUNDO) 876 vundkind = VCHNG; 877 wcursor = cursor + cnt; 878 vUD1 = cursor; vUD2 = wcursor; 879 CP(cursor, wcursor); 880 prepapp(); 881 vappend('r', cnt, 0); 882 *lastcp++ = INS[0]; 883 setLAST(); 884 } 885 886 /* 887 * Yank. 888 * 889 * Yanking to string registers occurs for free (essentially) 890 * in the routine xdw(). 891 */ 892 vyankit() 893 { 894 register int cnt; 895 896 if (wdot) { 897 if ((cnt = xdw()) < 0) 898 return; 899 vremote(cnt, yank, 0); 900 setpk(); 901 notenam = "yank"; 902 if (FIXUNDO) 903 vundkind = VNONE; 904 DEL[0] = 0; 905 wdot = NOLINE; 906 if (notecnt <= vcnt - vcline && notecnt < value(REPORT)) 907 notecnt = 0; 908 vrepaint(cursor); 909 return; 910 } 911 takeout(DEL); 912 } 913 914 /* 915 * Set pkill variables so a put can 916 * know how to put back partial text. 917 * This is necessary because undo needs the complete 918 * line images to be saved, while a put wants to trim 919 * the first and last lines. The compromise 920 * is for put to be more clever. 921 */ 922 setpk() 923 { 924 925 if (wcursor) { 926 pkill[0] = cursor; 927 pkill[1] = wcursor; 928 } 929 } 930