|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid = "@(#)ex_vops.c 7.7 (Berkeley) 6/7/85"; ! 9: #endif not lint ! 10: ! 11: #include "ex.h" ! 12: #include "ex_tty.h" ! 13: #include "ex_vis.h" ! 14: ! 15: /* ! 16: * This file defines the operation sequences which interface the ! 17: * logical changes to the file buffer with the internal and external ! 18: * display representations. ! 19: */ ! 20: ! 21: /* ! 22: * Undo. ! 23: * ! 24: * Undo is accomplished in two ways. We often for small changes in the ! 25: * current line know how (in terms of a change operator) how the change ! 26: * occurred. Thus on an intelligent terminal we can undo the operation ! 27: * by another such operation, using insert and delete character ! 28: * stuff. The pointers vU[AD][12] index the buffer vutmp when this ! 29: * is possible and provide the necessary information. ! 30: * ! 31: * The other case is that the change involved multiple lines or that ! 32: * we have moved away from the line or forgotten how the change was ! 33: * accomplished. In this case we do a redisplay and hope that the ! 34: * low level optimization routines (which don't look for winning ! 35: * via insert/delete character) will not lose too badly. ! 36: */ ! 37: char *vUA1, *vUA2; ! 38: char *vUD1, *vUD2; ! 39: ! 40: vUndo() ! 41: { ! 42: ! 43: /* ! 44: * Avoid UU which clobbers ability to do u. ! 45: */ ! 46: if (vundkind == VCAPU || vUNDdot != dot) { ! 47: beep(); ! 48: return; ! 49: } ! 50: CP(vutmp, linebuf); ! 51: vUD1 = linebuf; vUD2 = strend(linebuf); ! 52: putmk1(dot, vUNDsav); ! 53: getDOT(); ! 54: vUA1 = linebuf; vUA2 = strend(linebuf); ! 55: vundkind = VCAPU; ! 56: if (state == ONEOPEN || state == HARDOPEN) { ! 57: vjumpto(dot, vUNDcurs, 0); ! 58: return; ! 59: } ! 60: vdirty(vcline, 1); ! 61: vsyncCL(); ! 62: cursor = linebuf; ! 63: vfixcurs(); ! 64: } ! 65: ! 66: vundo(show) ! 67: bool show; /* if true update the screen */ ! 68: { ! 69: register int cnt; ! 70: register line *addr; ! 71: register char *cp; ! 72: char temp[LBSIZE]; ! 73: bool savenote; ! 74: int (*OO)(); ! 75: short oldhold = hold; ! 76: ! 77: switch (vundkind) { ! 78: ! 79: case VMANYINS: ! 80: wcursor = 0; ! 81: addr1 = undap1; ! 82: addr2 = undap2 - 1; ! 83: vsave(); ! 84: YANKreg('1'); ! 85: notecnt = 0; ! 86: /* fall into ... */ ! 87: ! 88: case VMANY: ! 89: case VMCHNG: ! 90: vsave(); ! 91: addr = dot - vcline; ! 92: notecnt = 1; ! 93: if (undkind == UNDPUT && undap1 == undap2) { ! 94: beep(); ! 95: break; ! 96: } ! 97: /* ! 98: * Undo() call below basically replaces undap1 to undap2-1 ! 99: * with dol through unddol-1. Hack screen image to ! 100: * reflect this replacement. ! 101: */ ! 102: if (show) ! 103: if (undkind == UNDMOVE) ! 104: vdirty(0, LINES); ! 105: else ! 106: vreplace(undap1 - addr, undap2 - undap1, ! 107: undkind == UNDPUT ? 0 : unddol - dol); ! 108: savenote = notecnt; ! 109: undo(1); ! 110: if (show && (vundkind != VMCHNG || addr != dot)) ! 111: killU(); ! 112: vundkind = VMANY; ! 113: cnt = dot - addr; ! 114: if (cnt < 0 || cnt > vcnt || state != VISUAL) { ! 115: if (show) ! 116: vjumpto(dot, NOSTR, '.'); ! 117: break; ! 118: } ! 119: if (!savenote) ! 120: notecnt = 0; ! 121: if (show) { ! 122: vcline = cnt; ! 123: vrepaint(vmcurs); ! 124: } ! 125: vmcurs = 0; ! 126: break; ! 127: ! 128: case VCHNG: ! 129: case VCAPU: ! 130: vundkind = VCHNG; ! 131: strcpy(temp, vutmp); ! 132: strcpy(vutmp, linebuf); ! 133: doomed = column(vUA2 - 1) - column(vUA1 - 1); ! 134: strcLIN(temp); ! 135: cp = vUA1; vUA1 = vUD1; vUD1 = cp; ! 136: cp = vUA2; vUA2 = vUD2; vUD2 = cp; ! 137: if (!show) ! 138: break; ! 139: cursor = vUD1; ! 140: if (state == HARDOPEN) { ! 141: doomed = 0; ! 142: vsave(); ! 143: vopen(dot, WBOT); ! 144: vnline(cursor); ! 145: break; ! 146: } ! 147: /* ! 148: * Pseudo insert command. ! 149: */ ! 150: vcursat(cursor); ! 151: OO = Outchar; Outchar = vinschar; hold |= HOLDQIK; ! 152: vprepins(); ! 153: temp[vUA2 - linebuf] = 0; ! 154: for (cp = &temp[vUA1 - linebuf]; *cp;) ! 155: putchar(*cp++); ! 156: Outchar = OO; hold = oldhold; ! 157: endim(); ! 158: physdc(cindent(), cindent() + doomed); ! 159: doomed = 0; ! 160: vdirty(vcline, 1); ! 161: vsyncCL(); ! 162: if (cursor > linebuf && cursor >= strend(linebuf)) ! 163: cursor--; ! 164: vfixcurs(); ! 165: break; ! 166: ! 167: case VNONE: ! 168: beep(); ! 169: break; ! 170: } ! 171: } ! 172: ! 173: /* ! 174: * Routine to handle a change inside a macro. ! 175: * Fromvis is true if we were called from a visual command (as ! 176: * opposed to an ex command). This has nothing to do with being ! 177: * in open/visual mode as :s/foo/bar is not fromvis. ! 178: */ ! 179: vmacchng(fromvis) ! 180: bool fromvis; ! 181: { ! 182: line *savedot, *savedol; ! 183: char *savecursor; ! 184: char savelb[LBSIZE]; ! 185: int nlines, more; ! 186: register line *a1, *a2; ! 187: char ch; /* DEBUG */ ! 188: int copyw(), copywR(); ! 189: ! 190: if (!inopen) ! 191: return; ! 192: if (!vmacp) ! 193: vch_mac = VC_NOTINMAC; ! 194: #ifdef TRACE ! 195: if (trace) ! 196: fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot); ! 197: #endif ! 198: if (vmacp && fromvis) ! 199: vsave(); ! 200: #ifdef TRACE ! 201: if (trace) ! 202: fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot); ! 203: #endif ! 204: switch(vch_mac) { ! 205: case VC_NOCHANGE: ! 206: vch_mac = VC_ONECHANGE; ! 207: break; ! 208: case VC_ONECHANGE: ! 209: /* Save current state somewhere */ ! 210: #ifdef TRACE ! 211: vudump("before vmacchng hairy case"); ! 212: #endif ! 213: savedot = dot; savedol = dol; savecursor = cursor; ! 214: CP(savelb, linebuf); ! 215: nlines = dol - zero; ! 216: while ((line *) endcore - truedol < nlines) ! 217: morelines(); ! 218: copyw(truedol+1, zero+1, nlines); ! 219: truedol += nlines; ! 220: ! 221: #ifdef TRACE ! 222: visdump("before vundo"); ! 223: #endif ! 224: /* Restore state as it was at beginning of macro */ ! 225: vundo(0); ! 226: #ifdef TRACE ! 227: visdump("after vundo"); ! 228: vudump("after vundo"); ! 229: #endif ! 230: ! 231: /* Do the saveall we should have done then */ ! 232: saveall(); ! 233: #ifdef TRACE ! 234: vudump("after saveall"); ! 235: #endif ! 236: ! 237: /* Restore current state from where saved */ ! 238: more = savedol - dol; /* amount we shift everything by */ ! 239: if (more) ! 240: (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol); ! 241: unddol += more; truedol += more; undap2 += more; ! 242: ! 243: truedol -= nlines; ! 244: copyw(zero+1, truedol+1, nlines); ! 245: dot = savedot; dol = savedol ; cursor = savecursor; ! 246: CP(linebuf, savelb); ! 247: vch_mac = VC_MANYCHANGE; ! 248: ! 249: /* Arrange that no further undo saving happens within macro */ ! 250: otchng = tchng; /* Copied this line blindly - bug? */ ! 251: inopen = -1; /* no need to save since it had to be 1 or -1 before */ ! 252: vundkind = VMANY; ! 253: #ifdef TRACE ! 254: vudump("after vmacchng"); ! 255: #endif ! 256: break; ! 257: case VC_NOTINMAC: ! 258: case VC_MANYCHANGE: ! 259: /* Nothing to do for various reasons. */ ! 260: break; ! 261: } ! 262: } ! 263: ! 264: /* ! 265: * Initialize undo information before an append. ! 266: */ ! 267: vnoapp() ! 268: { ! 269: ! 270: vUD1 = vUD2 = cursor; ! 271: } ! 272: ! 273: /* ! 274: * All the rest of the motion sequences have one or more ! 275: * cases to deal with. In the case wdot == 0, operation ! 276: * is totally within current line, from cursor to wcursor. ! 277: * If wdot is given, but wcursor is 0, then operation affects ! 278: * the inclusive line range. The hardest case is when both wdot ! 279: * and wcursor are given, then operation affects from line dot at ! 280: * cursor to line wdot at wcursor. ! 281: */ ! 282: ! 283: /* ! 284: * Move is simple, except for moving onto new lines in hardcopy open mode. ! 285: */ ! 286: vmove() ! 287: { ! 288: register int cnt; ! 289: ! 290: if (wdot) { ! 291: if (wdot < one || wdot > dol) { ! 292: beep(); ! 293: return; ! 294: } ! 295: cnt = wdot - dot; ! 296: wdot = NOLINE; ! 297: if (cnt) ! 298: killU(); ! 299: vupdown(cnt, wcursor); ! 300: return; ! 301: } ! 302: ! 303: /* ! 304: * When we move onto a new line, save information for U undo. ! 305: */ ! 306: if (vUNDdot != dot) { ! 307: vUNDsav = *dot; ! 308: vUNDcurs = wcursor; ! 309: vUNDdot = dot; ! 310: } ! 311: ! 312: /* ! 313: * In hardcopy open, type characters to left of cursor ! 314: * on new line, or back cursor up if its to left of where we are. ! 315: * In any case if the current line is ``rubbled'' i.e. has trashy ! 316: * looking overstrikes on it or \'s from deletes, we reprint ! 317: * so it is more comprehensible (and also because we can't work ! 318: * if we let it get more out of sync since column() won't work right. ! 319: */ ! 320: if (state == HARDOPEN) { ! 321: register char *cp; ! 322: if (rubble) { ! 323: register int c; ! 324: int oldhold = hold; ! 325: ! 326: sethard(); ! 327: cp = wcursor; ! 328: c = *cp; ! 329: *cp = 0; ! 330: hold |= HOLDDOL; ! 331: vreopen(WTOP, lineDOT(), vcline); ! 332: hold = oldhold; ! 333: *cp = c; ! 334: } else if (wcursor > cursor) { ! 335: vfixcurs(); ! 336: for (cp = cursor; *cp && cp < wcursor;) { ! 337: register int c = *cp++ & TRIM; ! 338: ! 339: putchar(c ? c : ' '); ! 340: } ! 341: } ! 342: } ! 343: vsetcurs(wcursor); ! 344: } ! 345: ! 346: /* ! 347: * Delete operator. ! 348: * ! 349: * Hard case of deleting a range where both wcursor and wdot ! 350: * are specified is treated as a special case of change and handled ! 351: * by vchange (although vchange may pass it back if it degenerates ! 352: * to a full line range delete.) ! 353: */ ! 354: vdelete(c) ! 355: char c; ! 356: { ! 357: register char *cp; ! 358: register int i; ! 359: ! 360: if (wdot) { ! 361: if (wcursor) { ! 362: vchange('d'); ! 363: return; ! 364: } ! 365: if ((i = xdw()) < 0) ! 366: return; ! 367: if (state != VISUAL) { ! 368: vgoto(LINE(0), 0); ! 369: vputchar('@'); ! 370: } ! 371: wdot = dot; ! 372: vremote(i, delete, 0); ! 373: notenam = "delete"; ! 374: DEL[0] = 0; ! 375: killU(); ! 376: vreplace(vcline, i, 0); ! 377: if (wdot > dol) ! 378: vcline--; ! 379: vrepaint(NOSTR); ! 380: return; ! 381: } ! 382: if (wcursor < linebuf) ! 383: wcursor = linebuf; ! 384: if (cursor == wcursor) { ! 385: beep(); ! 386: return; ! 387: } ! 388: i = vdcMID(); ! 389: cp = cursor; ! 390: setDEL(); ! 391: CP(cp, wcursor); ! 392: if (cp > linebuf && (cp[0] == 0 || c == '#')) ! 393: cp--; ! 394: if (state == HARDOPEN) { ! 395: bleep(i, cp); ! 396: cursor = cp; ! 397: return; ! 398: } ! 399: physdc(column(cursor - 1), i); ! 400: DEPTH(vcline) = 0; ! 401: vreopen(LINE(vcline), lineDOT(), vcline); ! 402: vsyncCL(); ! 403: vsetcurs(cp); ! 404: } ! 405: ! 406: /* ! 407: * Change operator. ! 408: * ! 409: * In a single line we mark the end of the changed area with '$'. ! 410: * On multiple whole lines, we clear the lines first. ! 411: * Across lines with both wcursor and wdot given, we delete ! 412: * and sync then append (but one operation for undo). ! 413: */ ! 414: vchange(c) ! 415: char c; ! 416: { ! 417: register char *cp; ! 418: register int i, ind, cnt; ! 419: line *addr; ! 420: ! 421: if (wdot) { ! 422: /* ! 423: * Change/delete of lines or across line boundaries. ! 424: */ ! 425: if ((cnt = xdw()) < 0) ! 426: return; ! 427: getDOT(); ! 428: if (wcursor && cnt == 1) { ! 429: /* ! 430: * Not really. ! 431: */ ! 432: wdot = 0; ! 433: if (c == 'd') { ! 434: vdelete(c); ! 435: return; ! 436: } ! 437: goto smallchange; ! 438: } ! 439: if (cursor && wcursor) { ! 440: /* ! 441: * Across line boundaries, but not ! 442: * necessarily whole lines. ! 443: * Construct what will be left. ! 444: */ ! 445: *cursor = 0; ! 446: strcpy(genbuf, linebuf); ! 447: getline(*wdot); ! 448: if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) { ! 449: getDOT(); ! 450: beep(); ! 451: return; ! 452: } ! 453: strcat(genbuf, wcursor); ! 454: if (c == 'd' && *vpastwh(genbuf) == 0) { ! 455: /* ! 456: * Although this is a delete ! 457: * spanning line boundaries, what ! 458: * would be left is all white space, ! 459: * so take it all away. ! 460: */ ! 461: wcursor = 0; ! 462: getDOT(); ! 463: op = 0; ! 464: notpart(lastreg); ! 465: notpart('1'); ! 466: vdelete(c); ! 467: return; ! 468: } ! 469: ind = -1; ! 470: } else if (c == 'd' && wcursor == 0) { ! 471: vdelete(c); ! 472: return; ! 473: } else ! 474: #ifdef LISPCODE ! 475: /* ! 476: * We are just substituting text for whole lines, ! 477: * so determine the first autoindent. ! 478: */ ! 479: if (value(LISP) && value(AUTOINDENT)) ! 480: ind = lindent(dot); ! 481: else ! 482: #endif ! 483: ind = whitecnt(linebuf); ! 484: i = vcline >= 0 ? LINE(vcline) : WTOP; ! 485: ! 486: /* ! 487: * Delete the lines from the buffer, ! 488: * and remember how the partial stuff came about in ! 489: * case we are told to put. ! 490: */ ! 491: addr = dot; ! 492: vremote(cnt, delete, 0); ! 493: setpk(); ! 494: notenam = "delete"; ! 495: if (c != 'd') ! 496: notenam = "change"; ! 497: /* ! 498: * If DEL[0] were nonzero, put would put it back ! 499: * rather than the deleted lines. ! 500: */ ! 501: DEL[0] = 0; ! 502: if (cnt > 1) ! 503: killU(); ! 504: ! 505: /* ! 506: * Now hack the screen image coordination. ! 507: */ ! 508: vreplace(vcline, cnt, 0); ! 509: wdot = NOLINE; ! 510: noteit(0); ! 511: vcline--; ! 512: if (addr <= dol) ! 513: dot--; ! 514: ! 515: /* ! 516: * If this is a across line delete/change, ! 517: * cursor stays where it is; just splice together the pieces ! 518: * of the new line. Otherwise generate a autoindent ! 519: * after a S command. ! 520: */ ! 521: if (ind >= 0) { ! 522: *genindent(ind) = 0; ! 523: vdoappend(genbuf); ! 524: } else { ! 525: vmcurs = cursor; ! 526: strcLIN(genbuf); ! 527: vdoappend(linebuf); ! 528: } ! 529: ! 530: /* ! 531: * Indicate a change on hardcopies by ! 532: * erasing the current line. ! 533: */ ! 534: if (c != 'd' && state != VISUAL && state != HARDOPEN) { ! 535: int oldhold = hold; ! 536: ! 537: hold |= HOLDAT, vclrlin(i, dot), hold = oldhold; ! 538: } ! 539: ! 540: /* ! 541: * Open the line (logically) on the screen, and ! 542: * update the screen tail. Unless we are really a delete ! 543: * go off and gather up inserted characters. ! 544: */ ! 545: vcline++; ! 546: if (vcline < 0) ! 547: vcline = 0; ! 548: vopen(dot, i); ! 549: vsyncCL(); ! 550: noteit(1); ! 551: if (c != 'd') { ! 552: if (ind >= 0) { ! 553: cursor = linebuf; ! 554: linebuf[0] = 0; ! 555: vfixcurs(); ! 556: } else { ! 557: ind = 0; ! 558: vcursat(cursor); ! 559: } ! 560: vappend('x', 1, ind); ! 561: return; ! 562: } ! 563: if (*cursor == 0 && cursor > linebuf) ! 564: cursor--; ! 565: vrepaint(cursor); ! 566: return; ! 567: } ! 568: ! 569: smallchange: ! 570: /* ! 571: * The rest of this is just low level hacking on changes ! 572: * of small numbers of characters. ! 573: */ ! 574: if (wcursor < linebuf) ! 575: wcursor = linebuf; ! 576: if (cursor == wcursor) { ! 577: beep(); ! 578: return; ! 579: } ! 580: i = vdcMID(); ! 581: cp = cursor; ! 582: if (state != HARDOPEN) ! 583: vfixcurs(); ! 584: ! 585: /* ! 586: * Put out the \\'s indicating changed text in hardcopy, ! 587: * or mark the end of the change with $ if not hardcopy. ! 588: */ ! 589: if (state == HARDOPEN) ! 590: bleep(i, cp); ! 591: else { ! 592: vcursbef(wcursor); ! 593: putchar('$'); ! 594: i = cindent(); ! 595: } ! 596: ! 597: /* ! 598: * Remember the deleted text for possible put, ! 599: * and then prepare and execute the input portion of the change. ! 600: */ ! 601: cursor = cp; ! 602: setDEL(); ! 603: CP(cursor, wcursor); ! 604: if (state != HARDOPEN) { ! 605: vcursaft(cursor - 1); ! 606: doomed = i - cindent(); ! 607: } else { ! 608: /* ! 609: sethard(); ! 610: wcursor = cursor; ! 611: cursor = linebuf; ! 612: vgoto(outline, value(NUMBER) << 3); ! 613: vmove(); ! 614: */ ! 615: doomed = 0; ! 616: } ! 617: prepapp(); ! 618: vappend('c', 1, 0); ! 619: } ! 620: ! 621: /* ! 622: * Open new lines. ! 623: * ! 624: * Tricky thing here is slowopen. This causes display updating ! 625: * to be held off so that 300 baud dumb terminals don't lose badly. ! 626: * This also suppressed counts, which otherwise say how many blank ! 627: * space to open up. Counts are also suppressed on intelligent terminals. ! 628: * Actually counts are obsoleted, since if your terminal is slow ! 629: * you are better off with slowopen. ! 630: */ ! 631: voOpen(c, cnt) ! 632: int c; /* mjm: char --> int */ ! 633: register int cnt; ! 634: { ! 635: register int ind = 0, i; ! 636: short oldhold = hold; ! 637: int oldmask; ! 638: ! 639: if (value(SLOWOPEN) || value(REDRAW) && AL && DL) ! 640: cnt = 1; ! 641: oldmask = sigblock(sigmask(SIGWINCH)); ! 642: vsave(); ! 643: setLAST(); ! 644: if (value(AUTOINDENT)) ! 645: ind = whitecnt(linebuf); ! 646: if (c == 'O') { ! 647: vcline--; ! 648: dot--; ! 649: if (dot > zero) ! 650: getDOT(); ! 651: } ! 652: if (value(AUTOINDENT)) { ! 653: #ifdef LISPCODE ! 654: if (value(LISP)) ! 655: ind = lindent(dot + 1); ! 656: #endif ! 657: } ! 658: killU(); ! 659: prepapp(); ! 660: if (FIXUNDO) ! 661: vundkind = VMANY; ! 662: if (state != VISUAL) ! 663: c = WBOT + 1; ! 664: else { ! 665: c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); ! 666: if (c < ZERO) ! 667: c = ZERO; ! 668: i = LINE(vcline + 1) - c; ! 669: if (i < cnt && c <= WBOT && (!AL || !DL)) ! 670: vinslin(c, cnt - i, vcline); ! 671: } ! 672: *genindent(ind) = 0; ! 673: vdoappend(genbuf); ! 674: vcline++; ! 675: oldhold = hold; ! 676: hold |= HOLDROL; ! 677: vopen(dot, c); ! 678: hold = oldhold; ! 679: if (value(SLOWOPEN)) ! 680: /* ! 681: * Oh, so lazy! ! 682: */ ! 683: vscrap(); ! 684: else ! 685: vsync1(LINE(vcline)); ! 686: cursor = linebuf; ! 687: linebuf[0] = 0; ! 688: vappend('o', 1, ind); ! 689: (void)sigsetmask(oldmask); ! 690: } ! 691: ! 692: /* ! 693: * > < and = shift operators. ! 694: * ! 695: * Note that =, which aligns lisp, is just a ragged sort of shift, ! 696: * since it never distributes text between lines. ! 697: */ ! 698: char vshnam[2] = { 'x', 0 }; ! 699: ! 700: vshftop() ! 701: { ! 702: register line *addr; ! 703: register int cnt; ! 704: ! 705: if ((cnt = xdw()) < 0) ! 706: return; ! 707: addr = dot; ! 708: vremote(cnt, vshift, 0); ! 709: vshnam[0] = op; ! 710: notenam = vshnam; ! 711: dot = addr; ! 712: vreplace(vcline, cnt, cnt); ! 713: if (state == HARDOPEN) ! 714: vcnt = 0; ! 715: vrepaint(NOSTR); ! 716: } ! 717: ! 718: /* ! 719: * !. ! 720: * ! 721: * Filter portions of the buffer through unix commands. ! 722: */ ! 723: vfilter() ! 724: { ! 725: register line *addr; ! 726: register int cnt; ! 727: char *oglobp; ! 728: short d; ! 729: ! 730: if ((cnt = xdw()) < 0) ! 731: return; ! 732: if (vglobp) ! 733: vglobp = uxb; ! 734: if (readecho('!')) ! 735: return; ! 736: oglobp = globp; globp = genbuf + 1; ! 737: d = peekc; ungetchar(0); ! 738: CATCH ! 739: fixech(); ! 740: unix0(0); ! 741: ONERR ! 742: splitw = 0; ! 743: ungetchar(d); ! 744: vrepaint(cursor); ! 745: globp = oglobp; ! 746: return; ! 747: ENDCATCH ! 748: ungetchar(d); globp = oglobp; ! 749: addr = dot; ! 750: CATCH ! 751: vgoto(WECHO, 0); flusho(); ! 752: vremote(cnt, filter, 2); ! 753: ONERR ! 754: vdirty(0, LINES); ! 755: ENDCATCH ! 756: if (dot == zero && dol > zero) ! 757: dot = one; ! 758: splitw = 0; ! 759: notenam = ""; ! 760: /* ! 761: * BUG: we shouldn't be depending on what undap2 and undap1 are, ! 762: * since we may be inside a macro. What's really wanted is the ! 763: * number of lines we read from the filter. However, the mistake ! 764: * will be an overestimate so it only results in extra work, ! 765: * it shouldn't cause any real screwups. ! 766: */ ! 767: vreplace(vcline, cnt, undap2 - undap1); ! 768: dot = addr; ! 769: if (dot > dol) { ! 770: dot--; ! 771: vcline--; ! 772: } ! 773: vrepaint(NOSTR); ! 774: } ! 775: ! 776: /* ! 777: * Xdw exchanges dot and wdot if appropriate and also checks ! 778: * that wdot is reasonable. Its name comes from ! 779: * xchange dotand wdot ! 780: */ ! 781: xdw() ! 782: { ! 783: register char *cp; ! 784: register int cnt; ! 785: /* ! 786: register int notp = 0; ! 787: */ ! 788: ! 789: if (wdot == NOLINE || wdot < one || wdot > dol) { ! 790: beep(); ! 791: return (-1); ! 792: } ! 793: vsave(); ! 794: setLAST(); ! 795: if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) { ! 796: register line *addr; ! 797: ! 798: vcline -= dot - wdot; ! 799: addr = dot; dot = wdot; wdot = addr; ! 800: cp = cursor; cursor = wcursor; wcursor = cp; ! 801: } ! 802: /* ! 803: * If a region is specified but wcursor is at the begining ! 804: * of the last line, then we move it to be the end of the ! 805: * previous line (actually off the end). ! 806: */ ! 807: if (cursor && wcursor == linebuf && wdot > dot) { ! 808: wdot--; ! 809: getDOT(); ! 810: if (vpastwh(linebuf) >= cursor) ! 811: wcursor = 0; ! 812: else { ! 813: getline(*wdot); ! 814: wcursor = strend(linebuf); ! 815: getDOT(); ! 816: } ! 817: /* ! 818: * Should prepare in caller for possible dot == wdot. ! 819: */ ! 820: } ! 821: cnt = wdot - dot + 1; ! 822: if (vreg) { ! 823: vremote(cnt, YANKreg, vreg); ! 824: /* ! 825: if (notp) ! 826: notpart(vreg); ! 827: */ ! 828: } ! 829: ! 830: /* ! 831: * Kill buffer code. If delete operator is c or d, then save ! 832: * the region in numbered buffers. ! 833: * ! 834: * BUG: This may be somewhat inefficient due ! 835: * to the way named buffer are implemented, ! 836: * necessitating some optimization. ! 837: */ ! 838: vreg = 0; ! 839: if (any(op, "cd")) { ! 840: vremote(cnt, YANKreg, '1'); ! 841: /* ! 842: if (notp) ! 843: notpart('1'); ! 844: */ ! 845: } ! 846: return (cnt); ! 847: } ! 848: ! 849: /* ! 850: * Routine for vremote to call to implement shifts. ! 851: */ ! 852: vshift() ! 853: { ! 854: ! 855: shift(op, 1); ! 856: } ! 857: ! 858: /* ! 859: * Replace a single character with the next input character. ! 860: * A funny kind of insert. ! 861: */ ! 862: vrep(cnt) ! 863: register int cnt; ! 864: { ! 865: register int i, c; ! 866: ! 867: if (cnt > strlen(cursor)) { ! 868: beep(); ! 869: return; ! 870: } ! 871: i = column(cursor + cnt - 1); ! 872: vcursat(cursor); ! 873: doomed = i - cindent(); ! 874: if (!vglobp) { ! 875: c = getesc(); ! 876: if (c == 0) { ! 877: vfixcurs(); ! 878: return; ! 879: } ! 880: ungetkey(c); ! 881: } ! 882: CP(vutmp, linebuf); ! 883: if (FIXUNDO) ! 884: vundkind = VCHNG; ! 885: wcursor = cursor + cnt; ! 886: vUD1 = cursor; vUD2 = wcursor; ! 887: CP(cursor, wcursor); ! 888: prepapp(); ! 889: vappend('r', cnt, 0); ! 890: *lastcp++ = INS[0]; ! 891: setLAST(); ! 892: } ! 893: ! 894: /* ! 895: * Yank. ! 896: * ! 897: * Yanking to string registers occurs for free (essentially) ! 898: * in the routine xdw(). ! 899: */ ! 900: vyankit() ! 901: { ! 902: register int cnt; ! 903: ! 904: if (wdot) { ! 905: if ((cnt = xdw()) < 0) ! 906: return; ! 907: vremote(cnt, yank, 0); ! 908: setpk(); ! 909: notenam = "yank"; ! 910: if (FIXUNDO) ! 911: vundkind = VNONE; ! 912: DEL[0] = 0; ! 913: wdot = NOLINE; ! 914: if (notecnt <= vcnt - vcline && notecnt < value(REPORT)) ! 915: notecnt = 0; ! 916: vrepaint(cursor); ! 917: return; ! 918: } ! 919: takeout(DEL); ! 920: } ! 921: ! 922: /* ! 923: * Set pkill variables so a put can ! 924: * know how to put back partial text. ! 925: * This is necessary because undo needs the complete ! 926: * line images to be saved, while a put wants to trim ! 927: * the first and last lines. The compromise ! 928: * is for put to be more clever. ! 929: */ ! 930: setpk() ! 931: { ! 932: ! 933: if (wcursor) { ! 934: pkill[0] = cursor; ! 935: pkill[1] = wcursor; ! 936: } ! 937: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.