1: /* Copyright (c) 1981 Regents of the University of California */ 2: static char *sccsid = "@(#)ex_vops.c 7.1 7/8/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: }