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

##### Functions

    ateopr            X
    back1             X
    bleep             X
    takeout           X
    vappend           X
    vdcMID            X
    vdoappend         X
    vgetline          X
    vgetsplit         X
    vmaxrep           X

##### Variables

    gobbled           X
    ogcursor          X
    vaifirst          X
    vsplitpt          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_vops2.c	6.8 (Berkeley) 6/7/85";
       9: #endif
      10:
      11: #include "ex.h"
      12: #include "ex_tty.h"
      13: #include "ex_vis.h"
      14:
      15: /*
      16:  * Low level routines for operations sequences,
      17:  * and mostly, insert mode (and a subroutine
      18:  * to read an input line, including in the echo area.)
      19:  */
      20: extern char *vUA1, *vUA2;       /* mjm: extern; also in ex_vops.c */
      21: extern char *vUD1, *vUD2;       /* mjm: extern; also in ex_vops.c */
      22:
      23: /*
      24:  * Obleeperate characters in hardcopy
      25:  * open with \'s.
      26:  */
      27: bleep(i, cp)
      28:     register int i;
      29:     char *cp;
      30: {
      31:
      32:     i -= column(cp);
      33:     do
      34:         putchar('\\' | QUOTE);
      35:     while (--i >= 0);
      36:     rubble = 1;
      37: }
      38:
      39: /*
      40:  * Common code for middle part of delete
      41:  * and change operating on parts of lines.
      42:  */
      43: vdcMID()
      44: {
      45:     register char *cp;
      46:
      47:     squish();
      48:     setLAST();
      49:     if (FIXUNDO)
      50:         vundkind = VCHNG, CP(vutmp, linebuf);
      51:     if (wcursor < cursor)
      52:         cp = wcursor, wcursor = cursor, cursor = cp;
      53:     vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
      54:     return (column(wcursor - 1));
      55: }
      56:
      57: /*
      58:  * Take text from linebuf and stick it
      59:  * in the VBSIZE buffer BUF.  Used to save
      60:  * deleted text of part of line.
      61:  */
      62: takeout(BUF)
      63:     char *BUF;
      64: {
      65:     register char *cp;
      66:
      67:     if (wcursor < linebuf)
      68:         wcursor = linebuf;
      69:     if (cursor == wcursor) {
      70:         beep();
      71:         return;
      72:     }
      73:     if (wcursor < cursor) {
      74:         cp = wcursor;
      75:         wcursor = cursor;
      76:         cursor = cp;
      77:     }
      78:     setBUF(BUF);
      79:     if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
      80:         beep();
      81: }
      82:
      83: /*
      84:  * Are we at the end of the printed representation of the
      85:  * line?  Used internally in hardcopy open.
      86:  */
      87: ateopr()
      88: {
      89:     register int i, c;
      90:     register char *cp = vtube[destline] + destcol;
      91:
      92:     for (i = WCOLS - destcol; i > 0; i--) {
      93:         c = *cp++;
      94:         if (c == 0)
      95:             return (1);
      96:         if (c != ' ' && (c & QUOTE) == 0)
      97:             return (0);
      98:     }
      99:     return (1);
     100: }
     101:
     102: /*
     103:  * Append.
     104:  *
     105:  * This routine handles the top level append, doing work
     106:  * as each new line comes in, and arranging repeatability.
     107:  * It also handles append with repeat counts, and calculation
     108:  * of autoindents for new lines.
     109:  */
     110: bool    vaifirst;
     111: bool    gobbled;
     112: char    *ogcursor;
     113:
     114: vappend(ch, cnt, indent)
     115:     int ch;     /* mjm: char --> int */
     116:     int cnt, indent;
     117: {
     118:     register int i;
     119:     register char *gcursor;
     120:     bool escape;
     121:     int repcnt, savedoomed;
     122:     short oldhold = hold;
     123:     long oldmask;
     124:
     125:     /*
     126: 	 * Before a move in hardopen when the line is dirty
     127: 	 * or we are in the middle of the printed representation,
     128: 	 * we retype the line to the left of the cursor so the
     129: 	 * insert looks clean.
     130: 	 */
     131:     if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
     132:         rubble = 1;
     133:         gcursor = cursor;
     134:         i = *gcursor;
     135:         *gcursor = ' ';
     136:         wcursor = gcursor;
     137:         vmove();
     138:         *gcursor = i;
     139:     }
     140:     vaifirst = indent == 0;
     141:
     142:     /*
     143: 	 * Handle replace character by (eventually)
     144: 	 * limiting the number of input characters allowed
     145: 	 * in the vgetline routine.
     146: 	 */
     147:     if (ch == 'r')
     148:         repcnt = 2;
     149:     else
     150:         repcnt = 0;
     151:
     152:     /*
     153: 	 * If an autoindent is specified, then
     154: 	 * generate a mixture of blanks to tabs to implement
     155: 	 * it and place the cursor after the indent.
     156: 	 * Text read by the vgetline routine will be placed in genbuf,
     157: 	 * so the indent is generated there.
     158: 	 */
     159:     if (value(AUTOINDENT) && indent != 0) {
     160:         gcursor = genindent(indent);
     161:         *gcursor = 0;
     162:         vgotoCL(qcolumn(cursor - 1, genbuf));
     163:     } else {
     164:         gcursor = genbuf;
     165:         *gcursor = 0;
     166:         if (ch == 'o')
     167:             vfixcurs();
     168:     }
     169:
     170:     /*
     171: 	 * Prepare for undo.  Pointers delimit inserted portion of line.
     172: 	 */
     173:     vUA1 = vUA2 = cursor;
     174:
     175:     /*
     176: 	 * If we are not in a repeated command and a ^@ comes in
     177: 	 * then this means the previous inserted text.
     178: 	 * If there is none or it was too long to be saved,
     179: 	 * then beep() and also arrange to undo any damage done
     180: 	 * so far (e.g. if we are a change.)
     181: 	 */
     182:     if ((vglobp && *vglobp == 0) || peekbr()) {
     183:         if ((INS[0] & (QUOTE|TRIM)) == OVERBUF) {
     184:             beep();
     185:             if (!splitw)
     186:                 ungetkey('u');
     187:             doomed = 0;
     188:             hold = oldhold;
     189:             return;
     190:         }
     191:         /*
     192: 		 * Unread input from INS.
     193: 		 * An escape will be generated at end of string.
     194: 		 * Hold off n^^2 type update on dumb terminals.
     195: 		 */
     196:         vglobp = INS;
     197:         hold |= HOLDQIK;
     198:     } else if (vglobp == 0)
     199:         /*
     200: 		 * Not a repeated command, get
     201: 		 * a new inserted text for repeat.
     202: 		 */
     203:         INS[0] = 0;
     204:
     205:     /*
     206: 	 * For wrapmargin to hack away second space after a '.'
     207: 	 * when the first space caused a line break we keep
     208: 	 * track that this happened in gobblebl, which says
     209: 	 * to gobble up a blank silently.
     210: 	 */
     211:     gobblebl = 0;
     212:
     213:     oldmask = sigblock(sigmask(SIGWINCH));
     214:     /*
     215: 	 * Text gathering loop.
     216: 	 * New text goes into genbuf starting at gcursor.
     217: 	 * cursor preserves place in linebuf where text will eventually go.
     218: 	 */
     219:     if (*cursor == 0 || state == CRTOPEN)
     220:         hold |= HOLDROL;
     221:     for (;;) {
     222:         if (ch == 'r' && repcnt == 0)
     223:             escape = 0;
     224:         else {
     225:             gcursor = vgetline(repcnt, gcursor, &escape, ch);
     226:
     227:             /*
     228: 			 * After an append, stick information
     229: 			 * about the ^D's and ^^D's and 0^D's in
     230: 			 * the repeated text buffer so repeated
     231: 			 * inserts of stuff indented with ^D as backtab's
     232: 			 * can work.
     233: 			 */
     234:             if (HADUP)
     235:                 addtext("^");
     236:             else if (HADZERO)
     237:                 addtext("0");
     238:             while (CDCNT > 0)
     239:                 addtext("\204"), CDCNT--;
     240:             if (gobbled)
     241:                 addtext(" ");
     242:             addtext(ogcursor);
     243:         }
     244:         repcnt = 0;
     245:
     246:         /*
     247: 		 * Smash the generated and preexisting indents together
     248: 		 * and generate one cleanly made out of tabs and spaces
     249: 		 * if we are using autoindent.
     250: 		 */
     251:         if (!vaifirst && value(AUTOINDENT)) {
     252:             i = fixindent(indent);
     253:             if (!HADUP)
     254:                 indent = i;
     255:             gcursor = strend(genbuf);
     256:         }
     257:
     258:         /*
     259: 		 * Limit the repetition count based on maximum
     260: 		 * possible line length; do output implied
     261: 		 * by further count (> 1) and cons up the new line
     262: 		 * in linebuf.
     263: 		 */
     264:         cnt = vmaxrep(ch, cnt);
     265:         CP(gcursor + 1, cursor);
     266:         do {
     267:             CP(cursor, genbuf);
     268:             if (cnt > 1) {
     269:                 int oldhold = hold;
     270:
     271:                 Outchar = vinschar;
     272:                 hold |= HOLDQIK;
     273:                 printf("%s", genbuf);
     274:                 hold = oldhold;
     275:                 Outchar = vputchar;
     276:             }
     277:             cursor += gcursor - genbuf;
     278:         } while (--cnt > 0);
     279:         endim();
     280:         vUA2 = cursor;
     281:         if (escape != '\n')
     282:             CP(cursor, gcursor + 1);
     283:
     284:         /*
     285: 		 * If doomed characters remain, clobber them,
     286: 		 * and reopen the line to get the display exact.
     287: 		 */
     288:         if (state != HARDOPEN) {
     289:             DEPTH(vcline) = 0;
     290:             savedoomed = doomed;
     291:             if (doomed > 0) {
     292:                 register int cind = cindent();
     293:
     294:                 physdc(cind, cind + doomed);
     295:                 doomed = 0;
     296:             }
     297:             i = vreopen(LINE(vcline), lineDOT(), vcline);
     298: #ifdef TRACE
     299:             if (trace)
     300:                 fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
     301: #endif
     302:             if (ch == 'R')
     303:                 doomed = savedoomed;
     304:         }
     305:
     306:         /*
     307: 		 * All done unless we are continuing on to another line.
     308: 		 */
     309:         if (escape != '\n')
     310:             break;
     311:
     312:         /*
     313: 		 * Set up for the new line.
     314: 		 * First save the current line, then construct a new
     315: 		 * first image for the continuation line consisting
     316: 		 * of any new autoindent plus the pushed ahead text.
     317: 		 */
     318:         killU();
     319:         addtext(gobblebl ? " " : "\n");
     320:         vsave();
     321:         cnt = 1;
     322:         if (value(AUTOINDENT)) {
     323: #ifdef LISPCODE
     324:             if (value(LISP))
     325:                 indent = lindent(dot + 1);
     326:             else
     327: #endif
     328:                  if (!HADUP && vaifirst)
     329:                 indent = whitecnt(linebuf);
     330:             vaifirst = 0;
     331:             strcLIN(vpastwh(gcursor + 1));
     332:             gcursor = genindent(indent);
     333:             *gcursor = 0;
     334:             if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
     335:                 gcursor = genbuf;
     336:             CP(gcursor, linebuf);
     337:         } else {
     338:             CP(genbuf, gcursor + 1);
     339:             gcursor = genbuf;
     340:         }
     341:
     342:         /*
     343: 		 * If we started out as a single line operation and are now
     344: 		 * turning into a multi-line change, then we had better yank
     345: 		 * out dot before it changes so that undo will work
     346: 		 * correctly later.
     347: 		 */
     348:         if (FIXUNDO && vundkind == VCHNG) {
     349:             vremote(1, yank, 0);
     350:             undap1--;
     351:         }
     352:
     353:         /*
     354: 		 * Now do the append of the new line in the buffer,
     355: 		 * and update the display.  If slowopen
     356: 		 * we don't do very much.
     357: 		 */
     358:         vdoappend(genbuf);
     359:         vundkind = VMANYINS;
     360:         vcline++;
     361:         if (state != VISUAL)
     362:             vshow(dot, NOLINE);
     363:         else {
     364:             i += LINE(vcline - 1);
     365:             vopen(dot, i);
     366:             if (value(SLOWOPEN))
     367:                 vscrap();
     368:             else
     369:                 vsync1(LINE(vcline));
     370:         }
     371:         strcLIN(gcursor);
     372:         *gcursor = 0;
     373:         cursor = linebuf;
     374:         vgotoCL(qcolumn(cursor - 1, genbuf));
     375:     }
     376:
     377:     /*
     378: 	 * All done with insertion, position the cursor
     379: 	 * and sync the screen.
     380: 	 */
     381:     hold = oldhold;
     382:     if (cursor > linebuf)
     383:         cursor--;
     384:     if (state != HARDOPEN)
     385:         vsyncCL();
     386:     else if (cursor > linebuf)
     387:         back1();
     388:     doomed = 0;
     389:     wcursor = cursor;
     390:     vmove();
     391:     (void)sigsetmask(oldmask);
     392: }
     393:
     394: /*
     395:  * Subroutine for vgetline to back up a single character position,
     396:  * backwards around end of lines (vgoto can't hack columns which are
     397:  * less than 0 in general).
     398:  */
     399: back1()
     400: {
     401:
     402:     vgoto(destline - 1, WCOLS + destcol - 1);
     403: }
     404:
     405: /*
     406:  * Get a line into genbuf after gcursor.
     407:  * Cnt limits the number of input characters
     408:  * accepted and is used for handling the replace
     409:  * single character command.  Aescaped is the location
     410:  * where we stick a termination indicator (whether we
     411:  * ended with an ESCAPE or a newline/return.
     412:  *
     413:  * We do erase-kill type processing here and also
     414:  * are careful about the way we do this so that it is
     415:  * repeatable.  (I.e. so that your kill doesn't happen,
     416:  * when you repeat an insert if it was escaped with \ the
     417:  * first time you did it.  commch is the command character
     418:  * involved, including the prompt for readline.
     419:  */
     420: char *
     421: vgetline(cnt, gcursor, aescaped, commch)
     422:     int cnt;
     423:     register char *gcursor;
     424:     bool *aescaped;
     425:     char commch;
     426: {
     427:     register int c, ch;
     428:     register char *cp;
     429:     int x, y, iwhite, backsl=0;
     430:     char *iglobp;
     431:     char cstr[2];
     432:     int (*OO)() = Outchar;
     433:
     434:     /*
     435: 	 * Clear the output state and counters
     436: 	 * for autoindent backwards motion (counts of ^D, etc.)
     437: 	 * Remember how much white space at beginning of line so
     438: 	 * as not to allow backspace over autoindent.
     439: 	 */
     440:     *aescaped = 0;
     441:     ogcursor = gcursor;
     442:     flusho();
     443:     CDCNT = 0;
     444:     HADUP = 0;
     445:     HADZERO = 0;
     446:     gobbled = 0;
     447:     iwhite = whitecnt(genbuf);
     448:     iglobp = vglobp;
     449:
     450:     /*
     451: 	 * Carefully avoid using vinschar in the echo area.
     452: 	 */
     453:     if (splitw)
     454:         Outchar = vputchar;
     455:     else {
     456:         Outchar = vinschar;
     457:         vprepins();
     458:     }
     459:     for (;;) {
     460:         backsl = 0;
     461:         if (gobblebl)
     462:             gobblebl--;
     463:         if (cnt != 0) {
     464:             cnt--;
     465:             if (cnt == 0)
     466:                 goto vadone;
     467:         }
     468:         c = getkey();
     469:         if (c != ATTN)
     470:             c &= (QUOTE|TRIM);
     471:         ch = c;
     472:         maphopcnt = 0;
     473:         if (vglobp == 0 && Peekkey == 0 && commch != 'r')
     474:             while ((ch = map(c, immacs)) != c) {
     475:                 c = ch;
     476:                 if (!value(REMAP))
     477:                     break;
     478:                 if (++maphopcnt > 256)
     479:                     error("Infinite macro loop");
     480:             }
     481:         if (!iglobp) {
     482:
     483:             /*
     484: 			 * Erase-kill type processing.
     485: 			 * Only happens if we were not reading
     486: 			 * from untyped input when we started.
     487: 			 * Map users erase to ^H, kill to -1 for switch.
     488: 			 */
     489: #ifndef USG3TTY
     490:             if (c == tty.sg_erase)
     491:                 c = CTRL(h);
     492:             else if (c == tty.sg_kill)
     493:                 c = -1;
     494: #else
     495:             if (c == tty.c_cc[VERASE])
     496:                 c = CTRL(h);
     497:             else if (c == tty.c_cc[VKILL])
     498:                 c = -1;
     499: #endif
     500:             switch (c) {
     501:
     502:             /*
     503: 			 * ^?		Interrupt drops you back to visual
     504: 			 *		command mode with an unread interrupt
     505: 			 *		still in the input buffer.
     506: 			 *
     507: 			 * ^\		Quit does the same as interrupt.
     508: 			 *		If you are a ex command rather than
     509: 			 *		a vi command this will drop you
     510: 			 *		back to command mode for sure.
     511: 			 */
     512:             case ATTN:
     513:             case QUIT:
     514:                 ungetkey(c);
     515:                 goto vadone;
     516:
     517:             /*
     518: 			 * ^H		Backs up a character in the input.
     519: 			 *
     520: 			 * BUG:		Can't back around line boundaries.
     521: 			 *		This is hard because stuff has
     522: 			 *		already been saved for repeat.
     523: 			 */
     524:             case CTRL(h):
     525: bakchar:
     526:                 cp = gcursor - 1;
     527:                 if (cp < ogcursor) {
     528:                     if (splitw) {
     529:                         /*
     530: 						 * Backspacing over readecho
     531: 						 * prompt. Pretend delete but
     532: 						 * don't beep.
     533: 						 */
     534:                         ungetkey(c);
     535:                         goto vadone;
     536:                     }
     537:                     beep();
     538:                     continue;
     539:                 }
     540:                 goto vbackup;
     541:
     542:             /*
     543: 			 * ^W		Back up a white/non-white word.
     544: 			 */
     545:             case CTRL(w):
     546:                 wdkind = 1;
     547:                 for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
     548:                     continue;
     549:                 for (c = wordch(cp - 1);
     550:                     cp > ogcursor && wordof(c, cp - 1); cp--)
     551:                     continue;
     552:                 goto vbackup;
     553:
     554:             /*
     555: 			 * users kill	Kill input on this line, back to
     556: 			 *		the autoindent.
     557: 			 */
     558:             case -1:
     559:                 cp = ogcursor;
     560: vbackup:
     561:                 if (cp == gcursor) {
     562:                     beep();
     563:                     continue;
     564:                 }
     565:                 endim();
     566:                 *cp = 0;
     567:                 c = cindent();
     568:                 vgotoCL(qcolumn(cursor - 1, genbuf));
     569:                 if (doomed >= 0)
     570:                     doomed += c - cindent();
     571:                 gcursor = cp;
     572:                 continue;
     573:
     574:             /*
     575: 			 * \		Followed by erase or kill
     576: 			 *		maps to just the erase or kill.
     577: 			 */
     578:             case '\\':
     579:                 x = destcol, y = destline;
     580:                 putchar('\\');
     581:                 vcsync();
     582:                 c = getkey();
     583: #ifndef USG3TTY
     584:                 if (c == tty.sg_erase || c == tty.sg_kill)
     585: #else
     586:                 if (c == tty.c_cc[VERASE]
     587:                     || c == tty.c_cc[VKILL])
     588: #endif
     589:                 {
     590:                     vgoto(y, x);
     591:                     if (doomed >= 0)
     592:                         doomed++;
     593:                     goto def;
     594:                 }
     595:                 ungetkey(c), c = '\\';
     596:                 backsl = 1;
     597:                 break;
     598:
     599:             /*
     600: 			 * ^Q		Super quote following character
     601: 			 *		Only ^@ is verboten (trapped at
     602: 			 *		a lower level) and \n forces a line
     603: 			 *		split so doesn't really go in.
     604: 			 *
     605: 			 * ^V		Synonym for ^Q
     606: 			 */
     607:             case CTRL(q):
     608:             case CTRL(v):
     609:                 x = destcol, y = destline;
     610:                 putchar('^');
     611:                 vgoto(y, x);
     612:                 c = getkey();
     613: #ifdef TIOCSETC
     614:                 if (c == ATTN)
     615:                     c = nttyc.t_intrc;
     616: #endif
     617:                 if (c != NL) {
     618:                     if (doomed >= 0)
     619:                         doomed++;
     620:                     goto def;
     621:                 }
     622:                 break;
     623:             }
     624:         }
     625:
     626:         /*
     627: 		 * If we get a blank not in the echo area
     628: 		 * consider splitting the window in the wrapmargin.
     629: 		 */
     630:         if (c != NL && !splitw) {
     631:             if (c == ' ' && gobblebl) {
     632:                 gobbled = 1;
     633:                 continue;
     634:             }
     635:             if (value(WRAPMARGIN) &&
     636:                 (outcol >= OCOLUMNS - value(WRAPMARGIN) ||
     637:                  backsl && outcol==0) &&
     638:                 commch != 'r') {
     639:                 /*
     640: 				 * At end of word and hit wrapmargin.
     641: 				 * Move the word to next line and keep going.
     642: 				 */
     643:                 wdkind = 1;
     644:                 *gcursor++ = c;
     645:                 if (backsl)
     646:                     *gcursor++ = getkey();
     647:                 *gcursor = 0;
     648:                 /*
     649: 				 * Find end of previous word if we are past it.
     650: 				 */
     651:                 for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--)
     652:                     ;
     653:                 if (outcol+(backsl?OCOLUMNS:0) - (gcursor-cp) >= OCOLUMNS - value(WRAPMARGIN)) {
     654:                     /*
     655: 					 * Find beginning of previous word.
     656: 					 */
     657:                     for (; cp>ogcursor && !isspace(cp[-1]); cp--)
     658:                         ;
     659:                     if (cp <= ogcursor) {
     660:                         /*
     661: 						 * There is a single word that
     662: 						 * is too long to fit.  Just
     663: 						 * let it pass, but beep for
     664: 						 * each new letter to warn
     665: 						 * the luser.
     666: 						 */
     667:                         c = *--gcursor;
     668:                         *gcursor = 0;
     669:                         beep();
     670:                         goto dontbreak;
     671:                     }
     672:                     /*
     673: 					 * Save it for next line.
     674: 					 */
     675:                     macpush(cp, 0);
     676:                     cp--;
     677:                 }
     678:                 macpush("\n", 0);
     679:                 /*
     680: 				 * Erase white space before the word.
     681: 				 */
     682:                 while (cp > ogcursor && isspace(cp[-1]))
     683:                     cp--;   /* skip blank */
     684:                 gobblebl = 3;
     685:                 goto vbackup;
     686:             }
     687:         dontbreak:;
     688:         }
     689:
     690:         /*
     691: 		 * Word abbreviation mode.
     692: 		 */
     693:         cstr[0] = c;
     694:         if (anyabbrs && gcursor > ogcursor && !wordch(cstr) && wordch(gcursor-1)) {
     695:                 int wdtype, abno;
     696:
     697:                 cstr[1] = 0;
     698:                 wdkind = 1;
     699:                 cp = gcursor - 1;
     700:                 for (wdtype = wordch(cp - 1);
     701:                     cp > ogcursor && wordof(wdtype, cp - 1); cp--)
     702:                     ;
     703:                 *gcursor = 0;
     704:                 for (abno=0; abbrevs[abno].mapto; abno++) {
     705:                     if (eq(cp, abbrevs[abno].cap)) {
     706:                         macpush(cstr, 0);
     707:                         macpush(abbrevs[abno].mapto);
     708:                         goto vbackup;
     709:                     }
     710:                 }
     711:         }
     712:
     713:         switch (c) {
     714:
     715:         /*
     716: 		 * ^M		Except in repeat maps to \n.
     717: 		 */
     718:         case CR:
     719:             if (vglobp)
     720:                 goto def;
     721:             c = '\n';
     722:             /* presto chango ... */
     723:
     724:         /*
     725: 		 * \n		Start new line.
     726: 		 */
     727:         case NL:
     728:             *aescaped = c;
     729:             goto vadone;
     730:
     731:         /*
     732: 		 * escape	End insert unless repeat and more to repeat.
     733: 		 */
     734:         case ESCAPE:
     735:             if (lastvgk)
     736:                 goto def;
     737:             goto vadone;
     738:
     739:         /*
     740: 		 * ^D		Backtab.
     741: 		 * ^T		Software forward tab.
     742: 		 *
     743: 		 *		Unless in repeat where this means these
     744: 		 *		were superquoted in.
     745: 		 */
     746:         case CTRL(d):
     747:         case CTRL(t):
     748:             if (vglobp)
     749:                 goto def;
     750:             /* fall into ... */
     751:
     752:         /*
     753: 		 * ^D|QUOTE	Is a backtab (in a repeated command).
     754: 		 */
     755:         case CTRL(d) | QUOTE:
     756:             *gcursor = 0;
     757:             cp = vpastwh(genbuf);
     758:             c = whitecnt(genbuf);
     759:             if (ch == CTRL(t)) {
     760:                 /*
     761: 				 * ^t just generates new indent replacing
     762: 				 * current white space rounded up to soft
     763: 				 * tab stop increment.
     764: 				 */
     765:                 if (cp != gcursor)
     766:                     /*
     767: 					 * BUG:		Don't hack ^T except
     768: 					 *		right after initial
     769: 					 *		white space.
     770: 					 */
     771:                     continue;
     772:                 cp = genindent(iwhite = backtab(c + value(SHIFTWIDTH) + 1));
     773:                 ogcursor = cp;
     774:                 goto vbackup;
     775:             }
     776:             /*
     777: 			 * ^D works only if we are at the (end of) the
     778: 			 * generated autoindent.  We count the ^D for repeat
     779: 			 * purposes.
     780: 			 */
     781:             if (c == iwhite && c != 0)
     782:                 if (cp == gcursor) {
     783:                     iwhite = backtab(c);
     784:                     CDCNT++;
     785:                     ogcursor = cp = genindent(iwhite);
     786:                     goto vbackup;
     787:                 } else if (&cp[1] == gcursor &&
     788:                     (*cp == '^' || *cp == '0')) {
     789:                     /*
     790: 					 * ^^D moves to margin, then back
     791: 					 * to current indent on next line.
     792: 					 *
     793: 					 * 0^D moves to margin and then
     794: 					 * stays there.
     795: 					 */
     796:                     HADZERO = *cp == '0';
     797:                     ogcursor = cp = genbuf;
     798:                     HADUP = 1 - HADZERO;
     799:                     CDCNT = 1;
     800:                     endim();
     801:                     back1();
     802:                     vputchar(' ');
     803:                     goto vbackup;
     804:                 }
     805:             if (vglobp && vglobp - iglobp >= 2 &&
     806:                 (vglobp[-2] == '^' || vglobp[-2] == '0')
     807:                 && gcursor == ogcursor + 1)
     808:                 goto bakchar;
     809:             continue;
     810:
     811:         default:
     812:             /*
     813: 			 * Possibly discard control inputs.
     814: 			 */
     815:             if (!vglobp && junk(c)) {
     816:                 beep();
     817:                 continue;
     818:             }
     819: def:
     820:             if (!backsl) {
     821:                 int cnt;
     822:                 putchar(c);
     823:                 flush();
     824:             }
     825:             if (gcursor > &genbuf[LBSIZE - 2])
     826:                 error("Line too long");
     827:             *gcursor++ = c & TRIM;
     828:             vcsync();
     829:             if (value(SHOWMATCH) && !iglobp)
     830:                 if (c == ')' || c == '}')
     831:                     lsmatch(gcursor);
     832:             continue;
     833:         }
     834:     }
     835: vadone:
     836:     *gcursor = 0;
     837:     if (Outchar != termchar)
     838:         Outchar = OO;
     839:     endim();
     840:     return (gcursor);
     841: }
     842:
     843: int vgetsplit();
     844: char    *vsplitpt;
     845:
     846: /*
     847:  * Append the line in buffer at lp
     848:  * to the buffer after dot.
     849:  */
     850: vdoappend(lp)
     851:     char *lp;
     852: {
     853:     register int oing = inglobal;
     854:
     855:     vsplitpt = lp;
     856:     inglobal = 1;
     857:     ignore(append(vgetsplit, dot));
     858:     inglobal = oing;
     859: }
     860:
     861: /*
     862:  * Subroutine for vdoappend to pass to append.
     863:  */
     864: vgetsplit()
     865: {
     866:
     867:     if (vsplitpt == 0)
     868:         return (EOF);
     869:     strcLIN(vsplitpt);
     870:     vsplitpt = 0;
     871:     return (0);
     872: }
     873:
     874: /*
     875:  * Vmaxrep determines the maximum repetitition factor
     876:  * allowed that will yield total line length less than
     877:  * LBSIZE characters and also does hacks for the R command.
     878:  */
     879: vmaxrep(ch, cnt)
     880:     char ch;
     881:     register int cnt;
     882: {
     883:     register int len, replen;
     884:
     885:     if (cnt > LBSIZE - 2)
     886:         cnt = LBSIZE - 2;
     887:     replen = strlen(genbuf);
     888:     if (ch == 'R') {
     889:         len = strlen(cursor);
     890:         if (replen < len)
     891:             len = replen;
     892:         CP(cursor, cursor + len);
     893:         vUD2 += len;
     894:     }
     895:     len = strlen(linebuf);
     896:     if (len + cnt * replen <= LBSIZE - 2)
     897:         return (cnt);
     898:     cnt = (LBSIZE - 2 - len) / replen;
     899:     if (cnt == 0) {
     900:         vsave();
     901:         error("Line too long");
     902:     }
     903:     return (cnt);
     904: }

#### Defined functions

ateopr defined in line 87; used 4 times

- in line 131
- in /usr/src/ucb/ex/ex_cmds.c line 467
- in /usr/src/ucb/ex/ex_vput.c line 84
- in /usr/src/ucb/ex/ex_vwind.c line 228

back1 defined in line 399; used 3 times

- in line 387, 801
- in /usr/src/ucb/ex/ex_vput.c line 1173

bleep defined in line 27; used 2 times

- in /usr/src/ucb/ex/ex_vops.c line 395, 590

takeout defined in line 62; used 1 times

- in /usr/src/ucb/ex/ex_vops.c line 919

vappend defined in line 114; used 5 times

- in /usr/src/ucb/ex/ex_vmain.c line 627
- in /usr/src/ucb/ex/ex_vops.c line 560, 618, 688, 889

vdcMID defined in line 43; used 2 times

- in /usr/src/ucb/ex/ex_vops.c line 388, 580

vdoappend defined in line 850; used 5 times

- in line 358
- in /usr/src/ucb/ex/ex_v.c line 254
- in /usr/src/ucb/ex/ex_vops.c line 523-527(2), 673

vgetline defined in line 420; used 3 times

- in line 225
- in /usr/src/ucb/ex/ex.h line 353
- in /usr/src/ucb/ex/ex_vget.c line 222

vgetsplit defined in line 864; used 2 times

- in line 843, 857

vmaxrep defined in line 879; used 1 times

- in line 264

#### Defined variables

gobbled defined in line 111; used 3 times

- in line 240, 446, 632

ogcursor defined in line 112; used 16 times

- in line 242, 441, 527, 547-550(2), 559, 651, 657-659(2), 682, 694, 701, 773, 785, 797, 807

sccsid defined in line 8; never used
vaifirst defined in line 110; used 4 times

- in line 140, 251, 328-330(2)

vsplitpt defined in line 844; used 4 times

- in line 855, 867-870(3)

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