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