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

Defined functions

setpk defined in line 841; used 2 times
vUndo defined in line 31; used 1 times
vchange defined in line 321; used 2 times
vdelete defined in line 257; used 4 times
vfilter defined in line 644; used 1 times
vnoapp defined in line 168; used 1 times
voOpen defined in line 550; used 1 times
vrep defined in line 775; used 1 times
vshftop defined in line 619; used 1 times
vshift defined in line 765; used 2 times
vundo defined in line 59; used 1 times
vyankit defined in line 812; used 1 times
xdw defined in line 694; used 5 times

Defined variables

vUA1 defined in line 28; used 5 times
vUA2 defined in line 28; used 5 times
vUD1 defined in line 29; used 6 times
vUD2 defined in line 29; used 5 times
vshnam defined in line 617; used 2 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1874
Valid CSS Valid XHTML 1.0 Strict