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: }

Defined functions

setpk defined in line 918; used 2 times
vUndo defined in line 32; used 1 times
vchange defined in line 406; used 2 times
vdelete defined in line 346; used 4 times
vfilter defined in line 712; used 1 times
vnoapp defined in line 259; used 1 times
voOpen defined in line 623; used 1 times
vrep defined in line 850; used 1 times
vshftop defined in line 689; used 1 times
vshift defined in line 840; used 2 times
vundo defined in line 58; used 2 times
vyankit defined in line 888; used 1 times
xdw defined in line 769; used 5 times

Defined variables

sccsid defined in line 2; never used
vUA1 defined in line 29; used 7 times
vUA2 defined in line 29; used 8 times
vUD1 defined in line 30; used 7 times
vUD2 defined in line 30; used 7 times
vshnam defined in line 687; used 2 times
Last modified: 1981-07-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2512
Valid CSS Valid XHTML 1.0 Strict