|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_vops.c 6.3 10/23/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: 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: char c; ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.