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: #if !defined(lint) && defined(DOSCCS)
   8: static char *sccsid = "@(#)ex_vops.c	7.7 (Berkeley) 6/7/85";
   9: #endif
  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:     long 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: }

Defined functions

setpk defined in line 930; used 2 times
vUndo defined in line 40; used 1 times
vchange defined in line 414; used 2 times
vdelete defined in line 354; used 4 times
vfilter defined in line 723; used 1 times
vmove defined in line 286; used 4 times
vnoapp defined in line 267; used 1 times
voOpen defined in line 631; used 1 times
vrep defined in line 862; used 1 times
vshftop defined in line 700; used 1 times
vshift defined in line 852; used 2 times
vundo defined in line 66; used 2 times
vyankit defined in line 900; used 1 times
xdw defined in line 781; used 5 times

Defined variables

sccsid defined in line 8; never used
vUA1 defined in line 37; used 7 times
vUA2 defined in line 37; used 8 times
vUD1 defined in line 38; used 7 times
vUD2 defined in line 38; used 7 times
vshnam defined in line 698; used 2 times
Last modified: 1991-09-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2854
Valid CSS Valid XHTML 1.0 Strict