# 2.11BSD#431 - /usr/src/ucb/ex/ex_vops.c

##### Functions

    setpk             X
    vUndo             X
    vchange           X
    vdelete           X
    vfilter           X
    vmacchng          X
    vmove             X
    vnoapp            X
    voOpen            X
    vrep              X
    vshftop           X
    vshift            X
    vundo             X
    vyankit           X
    xdw               X

##### Variables

    vUA1              X
    vUA2              X
    vUD1              X
    vUD2              X
    vshnam            X

       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

- in line 493, 908

vUndo defined in line 40; used 1 times

- in /usr/src/ucb/ex/ex_vmain.c line 1101

vchange defined in line 414; used 2 times

- in line 362
- in /usr/src/ucb/ex/ex_vis.h line 267

vdelete defined in line 354; used 4 times

- in line 434, 466-471(2)
- in /usr/src/ucb/ex/ex_vis.h line 268

vfilter defined in line 723; used 1 times

- in /usr/src/ucb/ex/ex.h line 379

vmacchng defined in line 179; used 21 times

- in /usr/src/ucb/ex/ex_cmds.c line 174, 189, 238, 255, 316, 334, 380, 419, 537, 618, 635, 731, 823, 845
- in /usr/src/ucb/ex/ex_vmain.c line 485, 520, 609, 744
- in /usr/src/ucb/ex/ex_voper.c line 117, 124, 430

vmove defined in line 286; used 4 times

- in /usr/src/ucb/ex/ex_vis.h line 271
- in /usr/src/ucb/ex/ex_vops2.c line 137, 390
- in /usr/src/ucb/ex/ex_vwind.c line 468

vnoapp defined in line 267; used 1 times

- in /usr/src/ucb/ex/ex_vmain.c line 613

voOpen defined in line 631; used 1 times

- in /usr/src/ucb/ex/ex_vmain.c line 521

vrep defined in line 862; used 1 times

- in /usr/src/ucb/ex/ex_voper.c line 118

vshftop defined in line 700; used 1 times

- in /usr/src/ucb/ex/ex.h line 384

vshift defined in line 852; used 2 times

- in line 708
- in /usr/src/ucb/ex/ex_vis.h line 273

vundo defined in line 66; used 2 times

- in line 225
- in /usr/src/ucb/ex/ex_vmain.c line 1094

vyankit defined in line 900; used 1 times

- in /usr/src/ucb/ex/ex_vis.h line 274

xdw defined in line 781; used 5 times

- in line 365, 425, 705, 730, 905

#### Defined variables

sccsid defined in line 8; never used
vUA1 defined in line 37; used 7 times

- in line 54, 133-135(3), 154
- in /usr/src/ucb/ex/ex_vops2.c line 53, 173

vUA2 defined in line 37; used 8 times

- in line 54, 133-136(3), 153
- in /usr/src/ucb/ex/ex_vops2.c line 53, 173, 280

vUD1 defined in line 38; used 7 times

- in line 51, 135-139(3), 270, 886
- in /usr/src/ucb/ex/ex_vops2.c line 53

vUD2 defined in line 38; used 7 times

- in line 51, 136(2), 270, 886
- in /usr/src/ucb/ex/ex_vops2.c line 53, 893

vshnam defined in line 698; used 2 times

- in line 709-710(2)

Last modified: 1991-09-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2856 |