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

Defined functions

back1 defined in line 388; used 3 times
bleep defined in line 19; used 2 times
takeout defined in line 54; used 1 times
vappend defined in line 106; used 5 times
vdcMID defined in line 35; used 2 times
vdoappend defined in line 839; used 5 times
vgetline defined in line 409; used 3 times
vgetsplit defined in line 853; used 2 times
vmaxrep defined in line 868; used 1 times

Defined variables

gobbled defined in line 103; used 3 times
ogcursor defined in line 104; used 16 times
sccsid defined in line 2; never used
vaifirst defined in line 102; used 4 times
vsplitpt defined in line 833; used 4 times
Last modified: 1981-07-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1915
Valid CSS Valid XHTML 1.0 Strict