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

Defined functions

back1 defined in line 397; used 3 times
bleep defined in line 18; used 2 times
takeout defined in line 52; used 1 times
vappend defined in line 104; used 5 times
vdcMID defined in line 34; used 2 times
vdoappend defined in line 766; used 5 times
vgetline defined in line 417; used 3 times
vgetsplit defined in line 780; used 2 times
vmaxrep defined in line 795; used 1 times

Defined variables

gobbled defined in line 101; used 3 times
ogcursor defined in line 102; used 10 times
vUA1 defined in line 11; used 2 times
vUA2 defined in line 11; used 3 times
vUD1 defined in line 12; used 1 times
  • in line 43
vUD2 defined in line 12; used 2 times
vaifirst defined in line 100; used 4 times
vsplitpt defined in line 760; used 4 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1670
Valid CSS Valid XHTML 1.0 Strict