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: #ifndef lint
   8: static char *sccsid = "@(#)ex_put.c	7.9 (Berkeley) 6/7/85";
   9: #endif not lint
  10: 
  11: #include "ex.h"
  12: #include "ex_tty.h"
  13: #include "ex_vis.h"
  14: 
  15: /*
  16:  * Terminal driving and line formatting routines.
  17:  * Basic motion optimizations are done here as well
  18:  * as formatting of lines (printing of control characters,
  19:  * line numbering and the like).
  20:  */
  21: 
  22: /*
  23:  * The routines outchar, putchar and pline are actually
  24:  * variables, and these variables point at the current definitions
  25:  * of the routines.  See the routine setflav.
  26:  * We sometimes make outchar be routines which catch the characters
  27:  * to be printed, e.g. if we want to see how long a line is.
  28:  * During open/visual, outchar and putchar will be set to
  29:  * routines in the file ex_vput.c (vputchar, vinschar, etc.).
  30:  */
  31: int (*Outchar)() = termchar;
  32: int (*Putchar)() = normchar;
  33: int (*Pline)() = normline;
  34: 
  35: int (*
  36: setlist(t))()
  37:     bool t;
  38: {
  39:     register int (*P)();
  40: 
  41:     listf = t;
  42:     P = Putchar;
  43:     Putchar = t ? listchar : normchar;
  44:     return (P);
  45: }
  46: 
  47: int (*
  48: setnumb(t))()
  49:     bool t;
  50: {
  51:     register int (*P)();
  52: 
  53:     numberf = t;
  54:     P = Pline;
  55:     Pline = t ? numbline : normline;
  56:     return (P);
  57: }
  58: 
  59: /*
  60:  * Format c for list mode; leave things in common
  61:  * with normal print mode to be done by normchar.
  62:  */
  63: listchar(c)
  64:     register short c;
  65: {
  66: 
  67:     c &= (TRIM|QUOTE);
  68:     switch (c) {
  69: 
  70:     case '\t':
  71:     case '\b':
  72:         outchar('^');
  73:         c = ctlof(c);
  74:         break;
  75: 
  76:     case '\n':
  77:         break;
  78: 
  79:     case '\n' | QUOTE:
  80:         outchar('$');
  81:         break;
  82: 
  83:     default:
  84:         if (c & QUOTE)
  85:             break;
  86:         if (c < ' ' && c != '\n' || c == DELETE)
  87:             outchar('^'), c = ctlof(c);
  88:         break;
  89:     }
  90:     normchar(c);
  91: }
  92: 
  93: /*
  94:  * Format c for printing.  Handle funnies of upper case terminals
  95:  * and crocky hazeltines which don't have ~.
  96:  */
  97: normchar(c)
  98:     register short c;
  99: {
 100:     register char *colp;
 101: 
 102:     c &= (TRIM|QUOTE);
 103:     if (c == '~' && HZ) {
 104:         normchar('\\');
 105:         c = '^';
 106:     }
 107:     if (c & QUOTE)
 108:         switch (c) {
 109: 
 110:         case ' ' | QUOTE:
 111:         case '\b' | QUOTE:
 112:             break;
 113: 
 114:         case QUOTE:
 115:             return;
 116: 
 117:         default:
 118:             c &= TRIM;
 119:         }
 120:     else if (c < ' ' && (c != '\b' || !OS) && c != '\n' && c != '\t' || c == DELETE)
 121:         putchar('^'), c = ctlof(c);
 122:     else if (UPPERCASE)
 123:         if (isupper(c)) {
 124:             outchar('\\');
 125:             c = tolower(c);
 126:         } else {
 127:             colp = "({)}!|^~'`";
 128:             while (*colp++)
 129:                 if (c == *colp++) {
 130:                     outchar('\\');
 131:                     c = colp[-2];
 132:                     break;
 133:                 }
 134:         }
 135:     outchar(c);
 136: }
 137: 
 138: /*
 139:  * Print a line with a number.
 140:  */
 141: numbline(i)
 142:     int i;
 143: {
 144: 
 145:     if (shudclob)
 146:         slobber(' ');
 147:     printf("%6d  ", i);
 148:     normline();
 149: }
 150: 
 151: /*
 152:  * Normal line output, no numbering.
 153:  */
 154: normline()
 155: {
 156:     register char *cp;
 157: 
 158:     if (shudclob)
 159:         slobber(linebuf[0]);
 160:     /* pdp-11 doprnt is not reentrant so can't use "printf" here
 161: 	   in case we are tracing */
 162:     for (cp = linebuf; *cp;)
 163:         putchar(*cp++);
 164:     if (!inopen)
 165:         putchar('\n' | QUOTE);
 166: }
 167: 
 168: /*
 169:  * Given c at the beginning of a line, determine whether
 170:  * the printing of the line will erase or otherwise obliterate
 171:  * the prompt which was printed before.  If it won't, do it now.
 172:  */
 173: slobber(c)
 174:     int c;
 175: {
 176: 
 177:     shudclob = 0;
 178:     switch (c) {
 179: 
 180:     case '\t':
 181:         if (Putchar == listchar)
 182:             return;
 183:         break;
 184: 
 185:     default:
 186:         return;
 187: 
 188:     case ' ':
 189:     case 0:
 190:         break;
 191:     }
 192:     if (OS)
 193:         return;
 194:     flush();
 195:     putch(' ');
 196:     if (BC)
 197:         tputs(BC, 0, putch);
 198:     else
 199:         putch('\b');
 200: }
 201: 
 202: /*
 203:  * The output buffer is initialized with a useful error
 204:  * message so we don't have to keep it in data space.
 205:  */
 206: static  char linb[66];
 207: char *linp = linb;
 208: 
 209: /*
 210:  * Phadnl records when we have already had a complete line ending with \n.
 211:  * If another line starts without a flush, and the terminal suggests it,
 212:  * we switch into -nl mode so that we can send lineffeeds to avoid
 213:  * a lot of spacing.
 214:  */
 215: static  bool phadnl;
 216: 
 217: /*
 218:  * Indirect to current definition of putchar.
 219:  */
 220: putchar(c)
 221:     int c;
 222: {
 223: 
 224:     (*Putchar)(c);
 225: }
 226: 
 227: /*
 228:  * Termchar routine for command mode.
 229:  * Watch for possible switching to -nl mode.
 230:  * Otherwise flush into next level of buffering when
 231:  * small buffer fills or at a newline.
 232:  */
 233: termchar(c)
 234:     int c;
 235: {
 236: 
 237:     if (pfast == 0 && phadnl)
 238:         pstart();
 239:     if (c == '\n')
 240:         phadnl = 1;
 241:     else if (linp >= &linb[63])
 242:         flush1();
 243:     *linp++ = c;
 244:     if (linp >= &linb[63]) {
 245:         fgoto();
 246:         flush1();
 247:     }
 248: }
 249: 
 250: flush()
 251: {
 252: 
 253:     flush1();
 254:     flush2();
 255: }
 256: 
 257: /*
 258:  * Flush from small line buffer into output buffer.
 259:  * Work here is destroying motion into positions, and then
 260:  * letting fgoto do the optimized motion.
 261:  */
 262: flush1()
 263: {
 264:     register char *lp;
 265:     register short c;
 266: 
 267:     *linp = 0;
 268:     lp = linb;
 269:     while (*lp)
 270:         switch (c = *lp++) {
 271: 
 272:         case '\r':
 273:             destline += destcol / COLUMNS;
 274:             destcol = 0;
 275:             continue;
 276: 
 277:         case '\b':
 278:             if (destcol)
 279:                 destcol--;
 280:             continue;
 281: 
 282:         case ' ':
 283:             destcol++;
 284:             continue;
 285: 
 286:         case '\t':
 287:             destcol += value(TABSTOP) - destcol % value(TABSTOP);
 288:             continue;
 289: 
 290:         case '\n':
 291:             destline += destcol / COLUMNS + 1;
 292:             if (destcol != 0 && destcol % COLUMNS == 0)
 293:                 destline--;
 294:             destcol = 0;
 295:             continue;
 296: 
 297:         default:
 298:             fgoto();
 299:             for (;;) {
 300:                 if (AM == 0 && outcol == COLUMNS)
 301:                     fgoto();
 302:                 c &= TRIM;
 303:                 putch(c);
 304:                 if (c == '\b') {
 305:                     outcol--;
 306:                     destcol--;
 307:                 } else if (c >= ' ' && c != DELETE) {
 308:                     outcol++;
 309:                     destcol++;
 310:                     if (XN && outcol % COLUMNS == 0)
 311:                         putch('\r'), putch('\n');
 312:                 }
 313:                 c = *lp++;
 314:                 if (c <= ' ')
 315:                     break;
 316:             }
 317:             --lp;
 318:             continue;
 319:         }
 320:     linp = linb;
 321: }
 322: 
 323: flush2()
 324: {
 325: 
 326:     fgoto();
 327:     flusho();
 328:     pstop();
 329: }
 330: 
 331: /*
 332:  * Sync the position of the output cursor.
 333:  * Most work here is rounding for terminal boundaries getting the
 334:  * column position implied by wraparound or the lack thereof and
 335:  * rolling up the screen to get destline on the screen.
 336:  */
 337: fgoto()
 338: {
 339:     register int l, c;
 340: 
 341:     if (destcol > COLUMNS - 1) {
 342:         destline += destcol / COLUMNS;
 343:         destcol %= COLUMNS;
 344:     }
 345:     if (outcol > COLUMNS - 1) {
 346:         l = (outcol + 1) / COLUMNS;
 347:         outline += l;
 348:         outcol %= COLUMNS;
 349:         if (AM == 0) {
 350:             while (l > 0) {
 351:                 if (pfast)
 352:                     if (xCR)
 353:                         tputs(xCR, 0, putch);
 354:                     else
 355:                         putch('\r');
 356:                 if (xNL)
 357:                     tputs(xNL, 0, putch);
 358:                 else
 359:                     putch('\n');
 360:                 l--;
 361:             }
 362:             outcol = 0;
 363:         }
 364:         if (outline > LINES - 1) {
 365:             destline -= outline - (LINES - 1);
 366:             outline = LINES - 1;
 367:         }
 368:     }
 369:     if (destline > LINES - 1) {
 370:         l = destline;
 371:         destline = LINES - 1;
 372:         if (outline < LINES - 1) {
 373:             c = destcol;
 374:             if (pfast == 0 && (!CA || holdcm))
 375:                 destcol = 0;
 376:             fgoto();
 377:             destcol = c;
 378:         }
 379:         while (l > LINES - 1) {
 380:             /*
 381: 			 * The following linefeed (or simulation thereof)
 382: 			 * is supposed to scroll up the screen, since we
 383: 			 * are on the bottom line.  We make the assumption
 384: 			 * that linefeed will scroll.  If ns is in the
 385: 			 * capability list this won't work.  We should
 386: 			 * probably have an sc capability but sf will
 387: 			 * generally take the place if it works.
 388: 			 *
 389: 			 * Superbee glitch:  in the middle of the screen we
 390: 			 * have to use esc B (down) because linefeed screws up
 391: 			 * in "Efficient Paging" (what a joke) mode (which is
 392: 			 * essential in some SB's because CRLF mode puts garbage
 393: 			 * in at end of memory), but you must use linefeed to
 394: 			 * scroll since down arrow won't go past memory end.
 395: 			 * I turned this off after recieving Paul Eggert's
 396: 			 * Superbee description which wins better.
 397: 			 */
 398:             if (xNL /* && !XB */ && pfast)
 399:                 tputs(xNL, 0, putch);
 400:             else
 401:                 putch('\n');
 402:             l--;
 403:             if (pfast == 0)
 404:                 outcol = 0;
 405:         }
 406:     }
 407:     if (destline < outline && !(CA && !holdcm || UP != NOSTR))
 408:         destline = outline;
 409:     if (CA && !holdcm)
 410:         if (plod(costCM) > 0)
 411:             plod(0);
 412:         else
 413:             tputs(tgoto(CM, destcol, destline), 0, putch);
 414:     else
 415:         plod(0);
 416:     outline = destline;
 417:     outcol = destcol;
 418: }
 419: 
 420: /*
 421:  * Tab to column col by flushing and then setting destcol.
 422:  * Used by "set all".
 423:  */
 424: tab(col)
 425:     int col;
 426: {
 427: 
 428:     flush1();
 429:     destcol = col;
 430: }
 431: 
 432: /*
 433:  * Move (slowly) to destination.
 434:  * Hard thing here is using home cursor on really deficient terminals.
 435:  * Otherwise just use cursor motions, hacking use of tabs and overtabbing
 436:  * and backspace.
 437:  */
 438: 
 439: static int plodcnt, plodflg;
 440: 
 441: plodput(c)
 442: {
 443: 
 444:     if (plodflg)
 445:         plodcnt--;
 446:     else
 447:         putch(c);
 448: }
 449: 
 450: plod(cnt)
 451: {
 452:     register int i, j, k;
 453:     register int soutcol, soutline;
 454: 
 455:     plodcnt = plodflg = cnt;
 456:     soutcol = outcol;
 457:     soutline = outline;
 458:     /*
 459: 	 * Consider homing and moving down/right from there, vs moving
 460: 	 * directly with local motions to the right spot.
 461: 	 */
 462:     if (HO) {
 463:         /*
 464: 		 * i is the cost to home and tab/space to the right to
 465: 		 * get to the proper column.  This assumes ND space costs
 466: 		 * 1 char.  So i+destcol is cost of motion with home.
 467: 		 */
 468:         if (GT)
 469:             i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS));
 470:         else
 471:             i = destcol;
 472:         /*
 473: 		 * j is cost to move locally without homing
 474: 		 */
 475:         if (destcol >= outcol) {    /* if motion is to the right */
 476:             j = destcol / value(HARDTABS) - outcol / value(HARDTABS);
 477:             if (GT && j)
 478:                 j += destcol % value(HARDTABS);
 479:             else
 480:                 j = destcol - outcol;
 481:         } else
 482:             /* leftward motion only works if we can backspace. */
 483:             if (outcol - destcol <= i && (BS || BC))
 484:                 i = j = outcol - destcol; /* cheaper to backspace */
 485:             else
 486:                 j = i + 1; /* impossibly expensive */
 487: 
 488:         /* k is the absolute value of vertical distance */
 489:         k = outline - destline;
 490:         if (k < 0)
 491:             k = -k;
 492:         j += k;
 493: 
 494:         /*
 495: 		 * Decision.  We may not have a choice if no UP.
 496: 		 */
 497:         if (i + destline < j || (!UP && destline < outline)) {
 498:             /*
 499: 			 * Cheaper to home.  Do it now and pretend it's a
 500: 			 * regular local motion.
 501: 			 */
 502:             tputs(HO, 0, plodput);
 503:             outcol = outline = 0;
 504:         } else if (LL) {
 505:             /*
 506: 			 * Quickly consider homing down and moving from there.
 507: 			 * Assume cost of LL is 2.
 508: 			 */
 509:             k = (LINES - 1) - destline;
 510:             if (i + k + 2 < j && (k<=0 || UP)) {
 511:                 tputs(LL, 0, plodput);
 512:                 outcol = 0;
 513:                 outline = LINES - 1;
 514:             }
 515:         }
 516:     } else
 517:     /*
 518: 	 * No home and no up means it's impossible, so we return an
 519: 	 * incredibly big number to make cursor motion win out.
 520: 	 */
 521:         if (!UP && destline < outline)
 522:             return (500);
 523:     if (GT)
 524:         i = destcol % value(HARDTABS)
 525:             + destcol / value(HARDTABS);
 526:     else
 527:         i = destcol;
 528: /*
 529: 	if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
 530: 		j *= (k = strlen(BT));
 531: 		if ((k += (destcol&7)) > 4)
 532: 			j += 8 - (destcol&7);
 533: 		else
 534: 			j += k;
 535: 	} else
 536: */
 537:         j = outcol - destcol;
 538:     /*
 539: 	 * If we will later need a \n which will turn into a \r\n by
 540: 	 * the system or the terminal, then don't bother to try to \r.
 541: 	 */
 542:     if ((NONL || !pfast) && outline < destline)
 543:         goto dontcr;
 544:     /*
 545: 	 * If the terminal will do a \r\n and there isn't room for it,
 546: 	 * then we can't afford a \r.
 547: 	 */
 548:     if (NC && outline >= destline)
 549:         goto dontcr;
 550:     /*
 551: 	 * If it will be cheaper, or if we can't back up, then send
 552: 	 * a return preliminarily.
 553: 	 */
 554:     if (j > i + 1 || outcol > destcol && !BS && !BC) {
 555:         /*
 556: 		 * BUG: this doesn't take the (possibly long) length
 557: 		 * of xCR into account.
 558: 		 */
 559:         if (xCR)
 560:             tputs(xCR, 0, plodput);
 561:         else
 562:             plodput('\r');
 563:         if (NC) {
 564:             if (xNL)
 565:                 tputs(xNL, 0, plodput);
 566:             else
 567:                 plodput('\n');
 568:             outline++;
 569:         }
 570:         outcol = 0;
 571:     }
 572: dontcr:
 573:     /* Move down, if necessary, until we are at the desired line */
 574:     while (outline < destline) {
 575:         j = destline - outline;
 576:         if (j > costDP && DOWN_PARM) {
 577:             /* Win big on Tek 4025 */
 578:             tputs(tgoto(DOWN_PARM, 0, j), j, plodput);
 579:             outline += j;
 580:         }
 581:         else {
 582:             outline++;
 583:             if (xNL && pfast)
 584:                 tputs(xNL, 0, plodput);
 585:             else
 586:                 plodput('\n');
 587:         }
 588:         if (plodcnt < 0)
 589:             goto out;
 590:         if (NONL || pfast == 0)
 591:             outcol = 0;
 592:     }
 593:     if (BT)
 594:         k = strlen(BT); /* should probably be cost(BT) and moved out */
 595:     /* Move left, if necessary, to desired column */
 596:     while (outcol > destcol) {
 597:         if (plodcnt < 0)
 598:             goto out;
 599:         if (BT && !insmode && outcol - destcol > 4+k) {
 600:             tputs(BT, 0, plodput);
 601:             outcol--;
 602:             outcol -= outcol % value(HARDTABS); /* outcol &= ~7; */
 603:             continue;
 604:         }
 605:         j = outcol - destcol;
 606:         if (j > costLP && LEFT_PARM) {
 607:             tputs(tgoto(LEFT_PARM, 0, j), j, plodput);
 608:             outcol -= j;
 609:         }
 610:         else {
 611:             outcol--;
 612:             if (BC)
 613:                 tputs(BC, 0, plodput);
 614:             else
 615:                 plodput('\b');
 616:         }
 617:     }
 618:     /* Move up, if necessary, to desired row */
 619:     while (outline > destline) {
 620:         j = outline - destline;
 621:         if (UP_PARM && j > 1) {
 622:             /* Win big on Tek 4025 */
 623:             tputs(tgoto(UP_PARM, 0, j), j, plodput);
 624:             outline -= j;
 625:         }
 626:         else {
 627:             outline--;
 628:             tputs(UP, 0, plodput);
 629:         }
 630:         if (plodcnt < 0)
 631:             goto out;
 632:     }
 633:     /*
 634: 	 * Now move to the right, if necessary.  We first tab to
 635: 	 * as close as we can get.
 636: 	 */
 637:     if (GT && !insmode && destcol - outcol > 1) {
 638:         /* tab to right as far as possible without passing col */
 639:         for (;;) {
 640:             i = tabcol(outcol, value(HARDTABS));
 641:             if (i > destcol)
 642:                 break;
 643:             if (TA)
 644:                 tputs(TA, 0, plodput);
 645:             else
 646:                 plodput('\t');
 647:             outcol = i;
 648:         }
 649:         /* consider another tab and then some backspaces */
 650:         if (destcol - outcol > 4 && i < COLUMNS && (BC || BS)) {
 651:             if (TA)
 652:                 tputs(TA, 0, plodput);
 653:             else
 654:                 plodput('\t');
 655:             outcol = i;
 656:             /*
 657: 			 * Back up.  Don't worry about LEFT_PARM because
 658: 			 * it's never more than 4 spaces anyway.
 659: 			 */
 660:             while (outcol > destcol) {
 661:                 outcol--;
 662:                 if (BC)
 663:                     tputs(BC, 0, plodput);
 664:                 else
 665:                     plodput('\b');
 666:             }
 667:         }
 668:     }
 669:     /*
 670: 	 * We've tabbed as much as possible.  If we still need to go
 671: 	 * further (not exact or can't tab) space over.  This is a
 672: 	 * very common case when moving to the right with space.
 673: 	 */
 674:     while (outcol < destcol) {
 675:         j = destcol - outcol;
 676:         if (j > costRP && RIGHT_PARM) {
 677:             /*
 678: 			 * This probably happens rarely, if at all.
 679: 			 * It seems mainly useful for ANSI terminals
 680: 			 * with no hardware tabs, and I don't know
 681: 			 * of any such terminal at the moment.
 682: 			 */
 683:             tputs(tgoto(RIGHT_PARM, 0, j), j, plodput);
 684:             outcol += j;
 685:         }
 686:         else {
 687:             /*
 688: 			 * move one char to the right.  We don't use ND space
 689: 			 * because it's better to just print the char we are
 690: 			 * moving over.  There are various exceptions, however.
 691: 			 * If !inopen, vtube contains garbage.  If the char is
 692: 			 * a null or a tab we want to print a space.  Other
 693: 			 * random chars we use space for instead, too.
 694: 			 */
 695:             if (!inopen || vtube[outline]==NULL ||
 696:                 (i=vtube[outline][outcol]) < ' ')
 697:                 i = ' ';
 698:             if(i & QUOTE)   /* mjm: no sign extension on 3B */
 699:                 i = ' ';
 700:             if (insmode && ND)
 701:                 tputs(ND, 0, plodput);
 702:             else
 703:                 plodput(i);
 704:             outcol++;
 705:         }
 706:         if (plodcnt < 0)
 707:             goto out;
 708:     }
 709: out:
 710:     if (plodflg) {
 711:         outcol = soutcol;
 712:         outline = soutline;
 713:     }
 714:     return(plodcnt);
 715: }
 716: 
 717: /*
 718:  * An input line arrived.
 719:  * Calculate new (approximate) screen line position.
 720:  * Approximate because kill character echoes newline with
 721:  * no feedback and also because of long input lines.
 722:  */
 723: noteinp()
 724: {
 725: 
 726:     outline++;
 727:     if (outline > LINES - 1)
 728:         outline = LINES - 1;
 729:     destline = outline;
 730:     destcol = outcol = 0;
 731: }
 732: 
 733: /*
 734:  * Something weird just happened and we
 735:  * lost track of whats happening out there.
 736:  * Since we cant, in general, read where we are
 737:  * we just reset to some known state.
 738:  * On cursor addressible terminals setting to unknown
 739:  * will force a cursor address soon.
 740:  */
 741: termreset()
 742: {
 743: 
 744:     endim();
 745:     if (TI) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */
 746:         putpad(TI);  /*adb change -- emit terminal initial sequence */
 747:     destcol = 0;
 748:     destline = LINES - 1;
 749:     if (CA) {
 750:         outcol = UKCOL;
 751:         outline = UKCOL;
 752:     } else {
 753:         outcol = destcol;
 754:         outline = destline;
 755:     }
 756: }
 757: 
 758: /*
 759:  * Low level buffering, with the ability to drain
 760:  * buffered output without printing it.
 761:  */
 762: char    *obp = obuf;
 763: 
 764: draino()
 765: {
 766: 
 767:     obp = obuf;
 768: }
 769: 
 770: flusho()
 771: {
 772: 
 773:     if (obp != obuf) {
 774:         write(1, obuf, obp - obuf);
 775:         obp = obuf;
 776:     }
 777: }
 778: 
 779: putnl()
 780: {
 781: 
 782:     putchar('\n');
 783: }
 784: 
 785: putS(cp)
 786:     char *cp;
 787: {
 788: 
 789:     if (cp == NULL)
 790:         return;
 791:     while (*cp)
 792:         putch(*cp++);
 793: }
 794: 
 795: 
 796: putch(c)
 797:     int c;
 798: {
 799: 
 800: #ifdef OLD3BTTY     /* mjm */
 801:     if(c == '\n')   /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */
 802:         putch('\r');    /* mjm: vi does "stty -icanon" => -onlcr !! */
 803: #endif
 804:     *obp++ = c & 0177;
 805:     if (obp >= &obuf[sizeof obuf])
 806:         flusho();
 807: }
 808: 
 809: /*
 810:  * Miscellaneous routines related to output.
 811:  */
 812: 
 813: /*
 814:  * Put with padding
 815:  */
 816: putpad(cp)
 817:     char *cp;
 818: {
 819: 
 820:     flush();
 821:     tputs(cp, 0, putch);
 822: }
 823: 
 824: /*
 825:  * Set output through normal command mode routine.
 826:  */
 827: setoutt()
 828: {
 829: 
 830:     Outchar = termchar;
 831: }
 832: 
 833: /*
 834:  * Printf (temporarily) in list mode.
 835:  */
 836: /*VARARGS2*/
 837: lprintf(cp, dp)
 838:     char *cp, *dp;
 839: {
 840:     register int (*P)();
 841: 
 842:     P = setlist(1);
 843:     printf(cp, dp);
 844:     Putchar = P;
 845: }
 846: 
 847: /*
 848:  * Newline + flush.
 849:  */
 850: putNFL()
 851: {
 852: 
 853:     putnl();
 854:     flush();
 855: }
 856: 
 857: /*
 858:  * Try to start -nl mode.
 859:  */
 860: pstart()
 861: {
 862: 
 863:     if (NONL)
 864:         return;
 865:     if (!value(OPTIMIZE))
 866:         return;
 867:     if (ruptible == 0 || pfast)
 868:         return;
 869:     fgoto();
 870:     flusho();
 871:     pfast = 1;
 872:     normtty++;
 873: #ifndef USG3TTY
 874:     tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
 875: #else
 876:     tty = normf;
 877:     tty.c_oflag &= ~(ONLCR|TAB3);
 878:     tty.c_lflag &= ~ECHO;
 879: #endif
 880:     sTTY(1);
 881: }
 882: 
 883: /*
 884:  * Stop -nl mode.
 885:  */
 886: pstop()
 887: {
 888: 
 889:     if (inopen)
 890:         return;
 891:     phadnl = 0;
 892:     linp = linb;
 893:     draino();
 894:     normal(normf);
 895:     pfast &= ~1;
 896: }
 897: 
 898: /*
 899:  * Prep tty for open mode.
 900:  */
 901: ttymode
 902: ostart()
 903: {
 904:     ttymode f;
 905: 
 906:     if (!intty)
 907:         error("Open and visual must be used interactively");
 908:     gTTY(1);
 909:     normtty++;
 910: #ifndef USG3TTY
 911:     f = tty.sg_flags;
 912:     tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
 913: # ifdef CBREAK
 914:                             CBREAK;
 915: # else
 916:                             RAW;
 917: # endif
 918: # ifdef TIOCGETC
 919:     ttcharoff();
 920: # endif
 921: #else
 922:     f = tty;
 923:     tty = normf;
 924:     tty.c_iflag &= ~ICRNL;
 925:     tty.c_lflag &= ~(ECHO|ICANON);
 926:     tty.c_oflag &= ~(TAB3|ONLCR);
 927:     tty.c_cc[VMIN] = 1;
 928:     tty.c_cc[VTIME] = 1;
 929:     ttcharoff();
 930: #endif
 931:     sTTY(1);
 932:     tostart();
 933:     pfast |= 2;
 934:     return (f);
 935: }
 936: 
 937: /* actions associated with putting the terminal in open mode */
 938: tostart()
 939: {
 940:     putpad(VS);
 941:     putpad(KS);
 942:     if (!value(MESG)) {
 943:         if (ttynbuf[0] == 0) {
 944:             register char *tn;
 945:             if ((tn=ttyname(2)) == NULL &&
 946:                 (tn=ttyname(1)) == NULL &&
 947:                 (tn=ttyname(0)) == NULL)
 948:                 ttynbuf[0] = 1;
 949:             else
 950:                 strcpy(ttynbuf, tn);
 951:         }
 952:         if (ttynbuf[0] != 1) {
 953:             struct stat sbuf;
 954:             stat(ttynbuf, &sbuf);
 955:             ttymesg = sbuf.st_mode & 0777;
 956:             chmod(ttynbuf,
 957: #ifdef UCBV7
 958:     /*
 959: 	 * This applies to the UCB V7 Pdp-11 system with the
 960: 	 * -u write option only.
 961: 	 */
 962:                     0611    /* 11 = urgent only allowed */
 963: #else
 964:                     0600
 965: #endif
 966:                         );
 967:         }
 968:     }
 969: }
 970: 
 971: /*
 972:  * Turn off start/stop chars if they aren't the default ^S/^Q.
 973:  * This is so idiots who make esc their start/stop don't lose.
 974:  * We always turn off quit since datamedias send ^\ for their
 975:  * right arrow key.
 976:  */
 977: #ifdef TIOCGETC
 978: ttcharoff()
 979: {
 980:     nttyc.t_quitc = '\377';
 981:     if (nttyc.t_startc != CTRL(q))
 982:         nttyc.t_startc = '\377';
 983:     if (nttyc.t_stopc != CTRL(s))
 984:         nttyc.t_stopc = '\377';
 985: # ifdef TIOCLGET
 986:     nlttyc.t_suspc = '\377';    /* ^Z */
 987:     nlttyc.t_dsuspc = '\377';   /* ^Y */
 988:     nlttyc.t_flushc = '\377';   /* ^O */
 989:     nlttyc.t_lnextc = '\377';   /* ^V */
 990: # endif
 991: }
 992: #endif
 993: 
 994: #ifdef USG3TTY
 995: ttcharoff()
 996: {
 997:     tty.c_cc[VQUIT] = '\377';
 998: # ifdef VSTART
 999:     /*
1000: 	 * The following is sample code if USG ever lets people change
1001: 	 * their start/stop chars.  As long as they can't we can't get
1002: 	 * into trouble so we just leave them alone.
1003: 	 */
1004:     if (tty.c_cc[VSTART] != CTRL(q))
1005:         tty.c_cc[VSTART] = '\377';
1006:     if (tty.c_cc[VSTOP] != CTRL(s))
1007:         tty.c_cc[VSTOP] = '\377';
1008: # endif
1009: }
1010: #endif
1011: 
1012: /*
1013:  * Stop open, restoring tty modes.
1014:  */
1015: ostop(f)
1016:     ttymode f;
1017: {
1018: 
1019: #ifndef USG3TTY
1020:     pfast = (f & CRMOD) == 0;
1021: #else
1022:     pfast = (f.c_oflag & ONLCR) == 0;
1023: #endif
1024:     termreset(), fgoto(), flusho();
1025:     normal(f);
1026:     tostop();
1027: }
1028: 
1029: /* Actions associated with putting the terminal in the right mode. */
1030: tostop()
1031: {
1032:     putpad(VE);
1033:     putpad(KE);
1034:     if (!value(MESG) && ttynbuf[0]>1)
1035:         chmod(ttynbuf, ttymesg);
1036: }
1037: 
1038: #ifndef CBREAK
1039: /*
1040:  * Into cooked mode for interruptibility.
1041:  */
1042: vcook()
1043: {
1044: 
1045:     tty.sg_flags &= ~RAW;
1046:     sTTY(1);
1047: }
1048: 
1049: /*
1050:  * Back into raw mode.
1051:  */
1052: vraw()
1053: {
1054: 
1055:     tty.sg_flags |= RAW;
1056:     sTTY(1);
1057: }
1058: #endif
1059: 
1060: /*
1061:  * Restore flags to normal state f.
1062:  */
1063: normal(f)
1064:     ttymode f;
1065: {
1066: 
1067:     if (normtty > 0) {
1068:         setty(f);
1069:         normtty--;
1070:     }
1071: }
1072: 
1073: /*
1074:  * Straight set of flags to state f.
1075:  */
1076: ttymode
1077: setty(f)
1078:     ttymode f;
1079: {
1080: #ifndef USG3TTY
1081:     register int ot = tty.sg_flags;
1082: #else
1083:     ttymode ot;
1084:     ot = tty;
1085: #endif
1086: 
1087: #ifndef USG3TTY
1088:     if (f == normf) {
1089:         nttyc = ottyc;
1090: # ifdef TIOCLGET
1091:         nlttyc = olttyc;
1092: # endif
1093:     } else
1094:         ttcharoff();
1095:     tty.sg_flags = f;
1096: #else
1097:     if (tty.c_lflag & ICANON)
1098:         ttcharoff();
1099:     tty = f;
1100: #endif
1101:     sTTY(1);
1102:     return (ot);
1103: }
1104: 
1105: gTTY(i)
1106:     int i;
1107: {
1108: 
1109: #ifndef USG3TTY
1110:     ignore(gtty(i, &tty));
1111: # ifdef TIOCGETC
1112:     ioctl(i, TIOCGETC, &ottyc);
1113:     nttyc = ottyc;
1114: # endif
1115: # ifdef TIOCGLTC
1116:     ioctl(i, TIOCGLTC, &olttyc);
1117:     nlttyc = olttyc;
1118: # endif
1119: #else
1120:     ioctl(i, TCGETA, &tty);
1121: #endif
1122: }
1123: 
1124: /*
1125:  * sTTY: set the tty modes on file descriptor i to be what's
1126:  * currently in global "tty".  (Also use nttyc if needed.)
1127:  */
1128: sTTY(i)
1129:     int i;
1130: {
1131: 
1132: #ifndef USG3TTY
1133: # ifdef USG
1134:     /* Bug in USG tty driver, put out a DEL as a patch. */
1135:     if (tty.sg_ospeed >= B1200)
1136:         write(1, "\377", 1);
1137: # endif
1138: 
1139: # ifdef TIOCSETN
1140:     /* Don't flush typeahead if we don't have to */
1141:     ioctl(i, TIOCSETN, &tty);
1142: # else
1143:     /* We have to.  Too bad. */
1144:     stty(i, &tty);
1145: # endif
1146: 
1147: # ifdef TIOCGETC
1148:     /* Update the other random chars while we're at it. */
1149:     ioctl(i, TIOCSETC, &nttyc);
1150: # endif
1151: # ifdef TIOCSLTC
1152:     ioctl(i, TIOCSLTC, &nlttyc);
1153: # endif
1154: 
1155: #else
1156:     /* USG 3 very simple: just set everything */
1157:     ioctl(i, TCSETAW, &tty);
1158: #endif
1159: }
1160: 
1161: /*
1162:  * Print newline, or blank if in open/visual
1163:  */
1164: noonl()
1165: {
1166: 
1167:     putchar(Outchar != termchar ? ' ' : '\n');
1168: }

Defined functions

draino defined in line 764; used 4 times
fgoto defined in line 337; used 11 times
flush1 defined in line 262; used 7 times
flush2 defined in line 323; used 1 times
gTTY defined in line 1105; used 2 times
listchar defined in line 63; used 3 times
normal defined in line 1063; used 2 times
normchar defined in line 97; used 5 times
normline defined in line 154; used 4 times
noteinp defined in line 723; used 3 times
numbline defined in line 141; used 4 times
ostart defined in line 901; used 4 times
ostop defined in line 1015; used 3 times
plod defined in line 450; used 3 times
plodput defined in line 441; used 24 times
pstart defined in line 860; used 2 times
pstop defined in line 886; used 3 times
putS defined in line 785; never used
putch defined in line 796; used 24 times
putchar defined in line 220; used 7 times
sTTY defined in line 1128; used 5 times
slobber defined in line 173; used 2 times
tab defined in line 424; used 5 times
termchar defined in line 233; used 4 times
tostart defined in line 938; used 2 times
tostop defined in line 1030; used 3 times
ttcharoff defined in line 995; used 4 times

Defined variables

linb defined in line 206; used 6 times
linp defined in line 207; used 6 times
obp defined in line 762; used 6 times
phadnl defined in line 215; used 3 times
plodcnt defined in line 439; used 7 times
plodflg defined in line 439; used 3 times
sccsid defined in line 8; never used
t defined in line 49; used 6 times
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3310
Valid CSS Valid XHTML 1.0 Strict