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

Defined functions

draino defined in line 746; used 4 times
fgoto defined in line 319; used 11 times
flush1 defined in line 244; used 7 times
flush2 defined in line 305; used 1 times
gTTY defined in line 1087; used 2 times
listchar defined in line 63; used 3 times
normal defined in line 1045; used 2 times
normchar defined in line 96; used 4 times
normline defined in line 136; used 4 times
noteinp defined in line 705; used 3 times
numbline defined in line 123; used 4 times
ostart defined in line 883; used 4 times
ostop defined in line 997; used 3 times
plod defined in line 432; used 3 times
plodput defined in line 423; used 24 times
pstart defined in line 842; used 2 times
pstop defined in line 868; used 3 times
putS defined in line 767; never used
putch defined in line 778; used 24 times
putchar defined in line 202; used 7 times
sTTY defined in line 1110; used 5 times
slobber defined in line 155; used 2 times
tab defined in line 406; used 5 times
termchar defined in line 215; used 4 times
tostart defined in line 920; used 2 times
tostop defined in line 1012; used 3 times
ttcharoff defined in line 977; used 4 times

Defined variables

linb defined in line 188; used 6 times
linp defined in line 189; used 6 times
obp defined in line 744; used 6 times
phadnl defined in line 197; used 3 times
plodcnt defined in line 421; used 7 times
plodflg defined in line 421; used 3 times
sccsid defined in line 8; never used
t defined in line 49; used 6 times
Last modified: 1994-12-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6075
Valid CSS Valid XHTML 1.0 Strict