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