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

Defined functions

draino defined in line 756; used 4 times
fgoto defined in line 329; used 11 times
flush1 defined in line 254; used 7 times
flush2 defined in line 315; used 1 times
gTTY defined in line 1097; used 2 times
listchar defined in line 55; used 3 times
normal defined in line 1055; used 2 times
normchar defined in line 89; used 5 times
normline defined in line 146; used 4 times
noteinp defined in line 715; used 3 times
numbline defined in line 133; used 4 times
plod defined in line 442; used 3 times
plodput defined in line 433; used 24 times
pstart defined in line 852; used 2 times
pstop defined in line 878; used 3 times
putS defined in line 777; never used
putch defined in line 788; used 23 times
putchar defined in line 212; used 7 times
sTTY defined in line 1120; used 5 times
slobber defined in line 165; used 2 times
tab defined in line 416; used 5 times
termchar defined in line 225; used 4 times
tostart defined in line 930; used 2 times
tostop defined in line 1022; used 3 times
ttcharoff defined in line 987; used 4 times

Defined variables

linb defined in line 198; used 6 times
linp defined in line 199; used 6 times
obp defined in line 754; used 6 times
phadnl defined in line 207; used 3 times
plodcnt defined in line 431; used 7 times
plodflg defined in line 431; used 3 times
sccsid defined in line 2; never used
t defined in line 41; used 6 times
Last modified: 1981-10-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3199
Valid CSS Valid XHTML 1.0 Strict