|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char sccsid[] = "@(#)termout.c 4.2 (Berkeley) 5/30/89"; ! 20: #endif /* not lint */ ! 21: ! 22: #if defined(unix) ! 23: #include <signal.h> ! 24: #include <sgtty.h> ! 25: #endif ! 26: #include <stdio.h> ! 27: #include <curses.h> ! 28: #if defined(ultrix) ! 29: /* Some version of this OS has a bad definition for nonl() */ ! 30: #undef nl ! 31: #undef nonl ! 32: ! 33: #define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty)) ! 34: #define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty)) ! 35: #endif /* defined(ultrix) */ ! 36: ! 37: #include "../general/general.h" ! 38: ! 39: #include "terminal.h" ! 40: ! 41: #include "../api/disp_asc.h" ! 42: ! 43: #include "../ctlr/hostctlr.h" ! 44: #include "../ctlr/externs.h" ! 45: #include "../ctlr/declare.h" ! 46: #include "../ctlr/oia.h" ! 47: #include "../ctlr/screen.h" ! 48: #include "../ctlr/scrnctlr.h" ! 49: ! 50: #include "../general/globals.h" ! 51: ! 52: #include "../telextrn.h" ! 53: ! 54: #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ ! 55: CursorAddress:UnLocked? CursorAddress: HighestScreen()) ! 56: ! 57: ! 58: static int terminalCursorAddress; /* where the cursor is on term */ ! 59: static int screenInitd; /* the screen has been initialized */ ! 60: static int screenStopped; /* the screen has been stopped */ ! 61: static int max_changes_before_poll; /* how many characters before looking */ ! 62: /* at terminal and net again */ ! 63: ! 64: static int needToRing; /* need to ring terinal bell */ ! 65: static char *bellSequence = "\07"; /* bell sequence (may be replaced by ! 66: * VB during initialization) ! 67: */ ! 68: static WINDOW *bellwin = 0; /* The window the bell message is in */ ! 69: int bellwinup = 0; /* Are we up with it or not */ ! 70: ! 71: #if defined(unix) ! 72: static char *myKS, *myKE; ! 73: #endif /* defined(unix) */ ! 74: ! 75: ! 76: static int inHighlightMode = 0; ! 77: ScreenImage Terminal[MAXSCREENSIZE]; ! 78: ! 79: /* Variables for transparent mode */ ! 80: #if defined(unix) ! 81: static int tcflag = -1; /* transparent mode command flag */ ! 82: static int savefd[2]; /* for storing fds during transcom */ ! 83: extern int tin, tout; /* file descriptors */ ! 84: #endif /* defined(unix) */ ! 85: ! 86: ! 87: /* ! 88: * init_screen() ! 89: * ! 90: * Initialize variables used by screen. ! 91: */ ! 92: ! 93: void ! 94: init_screen() ! 95: { ! 96: bellwinup = 0; ! 97: inHighlightMode = 0; ! 98: ClearArray(Terminal); ! 99: } ! 100: ! 101: ! 102: /* OurExitString - designed to keep us from going through infinite recursion */ ! 103: ! 104: static void ! 105: OurExitString(string, value) ! 106: char *string; ! 107: int value; ! 108: { ! 109: static int recursion = 0; ! 110: ! 111: if (!recursion) { ! 112: recursion = 1; ! 113: ExitString(string, value); ! 114: } ! 115: } ! 116: ! 117: ! 118: /* DoARefresh */ ! 119: ! 120: static void ! 121: DoARefresh() ! 122: { ! 123: if (ERR == refresh()) { ! 124: OurExitString("ERR from refresh\n", 1); ! 125: } ! 126: } ! 127: ! 128: static void ! 129: GoAway(from, where) ! 130: char *from; /* routine that gave error */ ! 131: int where; /* cursor address */ ! 132: { ! 133: char foo[100]; ! 134: ! 135: sprintf(foo, "ERR from %s at %d (%d, %d)\n", ! 136: from, where, ScreenLine(where), ScreenLineOffset(where)); ! 137: OurExitString(foo, 1); ! 138: /* NOTREACHED */ ! 139: } ! 140: ! 141: /* What is the screen address of the attribute byte for the terminal */ ! 142: ! 143: static int ! 144: WhereTermAttrByte(p) ! 145: register int p; ! 146: { ! 147: register int i; ! 148: ! 149: i = p; ! 150: ! 151: do { ! 152: if (TermIsStartField(i)) { ! 153: return(i); ! 154: } ! 155: i = ScreenDec(i); ! 156: } while (i != p); ! 157: ! 158: return(LowestScreen()); /* unformatted screen... */ ! 159: } ! 160: ! 161: /* ! 162: * There are two algorithms for updating the screen. ! 163: * The first, SlowScreen() optimizes the line between the ! 164: * computer and the screen (say a 9600 baud line). To do ! 165: * this, we break out of the loop every so often to look ! 166: * at any pending input from the network (so that successive ! 167: * screens will only partially print until the final screen, ! 168: * the one the user possibly wants to see, is displayed ! 169: * in its entirety). ! 170: * ! 171: * The second algorithm tries to optimize CPU time (by ! 172: * being simpler) at the cost of the bandwidth to the ! 173: * screen. ! 174: * ! 175: * Of course, curses(3X) gets in here also. ! 176: */ ! 177: ! 178: ! 179: #if defined(NOT43) ! 180: static int ! 181: #else /* defined(NOT43) */ ! 182: static void ! 183: #endif /* defined(NOT43) */ ! 184: SlowScreen() ! 185: { ! 186: register int is, shouldbe, isattr, shouldattr; ! 187: register int pointer; ! 188: register int fieldattr, termattr; ! 189: register int columnsleft; ! 190: ! 191: #define NORMAL 0 ! 192: #define HIGHLIGHT 1 /* Mask bits */ ! 193: #define NONDISPLAY 4 /* Mask bits */ ! 194: #define UNDETERMINED 8 /* Mask bits */ ! 195: ! 196: #define DoAttributes(x) \ ! 197: switch (x&ATTR_DSPD_MASK) { \ ! 198: case ATTR_DSPD_NONDISPLAY: \ ! 199: x = NONDISPLAY; \ ! 200: break; \ ! 201: case ATTR_DSPD_HIGH: \ ! 202: x = HIGHLIGHT; \ ! 203: break; \ ! 204: default: \ ! 205: x = 0; \ ! 206: break; \ ! 207: } ! 208: ! 209: # define SetHighlightMode(x) \ ! 210: { \ ! 211: if ((x)&HIGHLIGHT) { \ ! 212: if (!inHighlightMode) { \ ! 213: inHighlightMode = HIGHLIGHT; \ ! 214: standout(); \ ! 215: } \ ! 216: } else { \ ! 217: if (inHighlightMode) { \ ! 218: inHighlightMode = 0; \ ! 219: standend(); \ ! 220: } \ ! 221: } \ ! 222: } ! 223: ! 224: # define DoCharacterAt(c,p) { \ ! 225: if (p != HighestScreen()) { \ ! 226: c = disp_asc[c&0xff]; \ ! 227: if (terminalCursorAddress != p) { \ ! 228: if (ERR == mvaddch(ScreenLine(p), \ ! 229: ScreenLineOffset(p), c)) {\ ! 230: GoAway("mvaddch", p); \ ! 231: } \ ! 232: } else { \ ! 233: if (ERR == addch(c)) {\ ! 234: GoAway("addch", p); \ ! 235: } \ ! 236: } \ ! 237: terminalCursorAddress = ScreenInc(p); \ ! 238: } \ ! 239: } ! 240: ! 241: ! 242: /* run through screen, printing out non-null lines */ ! 243: ! 244: /* There are two separate reasons for wanting to terminate this ! 245: * loop early. One is to respond to new input (either from ! 246: * the terminal or from the network [host]). For this reason, ! 247: * we expect to see 'HaveInput' come true when new input comes in. ! 248: * ! 249: * The second reason is a bit more difficult (for me) to understand. ! 250: * Basically, we don't want to get too far ahead of the characters that ! 251: * appear on the screen. Ideally, we would type out a few characters, ! 252: * wait until they appeared on the screen, then type out a few more. ! 253: * The reason for this is that the user, on seeing some characters ! 254: * appear on the screen may then start to type something. We would ! 255: * like to look at what the user types at about the same 'time' ! 256: * (measured by characters being sent to the terminal) that the ! 257: * user types them. For this reason, what we would like to do ! 258: * is update a bit, then call curses to do a refresh, flush the ! 259: * output to the terminal, then wait until the terminal data ! 260: * has been sent. ! 261: * ! 262: * Note that curses is useful for, among other things, deciding whether ! 263: * or not to send :ce: (clear to end of line), so we should call curses ! 264: * at end of lines (beginning of next lines). ! 265: * ! 266: * The problems here are the following: If we do lots of write(2)s, ! 267: * we will be doing lots of context switches, thus lots of overhead ! 268: * (which we have already). Second, if we do a select to wait for ! 269: * the output to drain, we have to contend with the fact that NOW ! 270: * we are scheduled to run, but who knows what the scheduler will ! 271: * decide when the output has caught up. ! 272: */ ! 273: ! 274: if (Highest >= HighestScreen()) { /* Could be > if screen shrunk... */ ! 275: Highest = ScreenDec(Highest); /* else, while loop will never end */ ! 276: } ! 277: if (Lowest < LowestScreen()) { ! 278: Lowest = LowestScreen(); /* could be -1 in some cases with ! 279: * unformatted screens. ! 280: */ ! 281: } ! 282: if (Highest >= (pointer = Lowest)) { ! 283: /* if there is anything to do, do it. We won't terminate ! 284: * the loop until we've gone at least to Highest. ! 285: */ ! 286: while ((pointer <= Highest) && !HaveInput) { ! 287: ! 288: /* point at the next place of disagreement */ ! 289: pointer += (bunequal(Host+pointer, Terminal+pointer, ! 290: (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]); ! 291: ! 292: /* ! 293: * How many characters to change until the end of the ! 294: * current line ! 295: */ ! 296: columnsleft = NumberColumns - ScreenLineOffset(pointer); ! 297: /* ! 298: * Make sure we are where we think we are. ! 299: */ ! 300: move(ScreenLine(pointer), ScreenLineOffset(pointer)); ! 301: ! 302: /* what is the field attribute of the current position */ ! 303: if (FormattedScreen()) { ! 304: fieldattr = FieldAttributes(pointer); ! 305: DoAttributes(fieldattr); ! 306: } else { ! 307: fieldattr = NORMAL; ! 308: } ! 309: if (TerminalFormattedScreen()) { ! 310: termattr = TermAttributes(pointer); ! 311: DoAttributes(termattr); ! 312: } else { ! 313: termattr = NORMAL; ! 314: } ! 315: ! 316: SetHighlightMode(fieldattr); ! 317: /* ! 318: * The following will terminate at least when we get back ! 319: * to the original 'pointer' location (since we force ! 320: * things to be equal). ! 321: */ ! 322: for (;;) { ! 323: if (IsStartField(pointer)) { ! 324: shouldbe = DISP_BLANK; ! 325: shouldattr = 0; ! 326: fieldattr = GetHost(pointer); ! 327: DoAttributes(fieldattr); ! 328: } else { ! 329: if (fieldattr&NONDISPLAY) { ! 330: shouldbe = DISP_BLANK; ! 331: } else { ! 332: shouldbe = GetHost(pointer); ! 333: } ! 334: shouldattr = fieldattr; ! 335: } ! 336: if (TermIsStartField(pointer)) { ! 337: is = DISP_BLANK; ! 338: isattr = 0; ! 339: termattr = UNDETERMINED; /* Need to find out AFTER update */ ! 340: } else { ! 341: if (termattr&NONDISPLAY) { ! 342: is = DISP_BLANK; ! 343: } else { ! 344: is = GetTerminal(pointer); ! 345: } ! 346: isattr = termattr; ! 347: } ! 348: if ((shouldbe == is) && (shouldattr == isattr) ! 349: && (GetHost(pointer) == GetTerminal(pointer)) ! 350: && (GetHost(ScreenInc(pointer)) ! 351: == GetTerminal(ScreenInc(pointer)))) { ! 352: break; ! 353: } ! 354: ! 355: if (shouldattr^inHighlightMode) { ! 356: SetHighlightMode(shouldattr); ! 357: } ! 358: ! 359: DoCharacterAt(shouldbe, pointer); ! 360: if (IsStartField(pointer)) { ! 361: TermNewField(pointer, FieldAttributes(pointer)); ! 362: termattr = GetTerminal(pointer); ! 363: DoAttributes(termattr); ! 364: } else { ! 365: SetTerminal(pointer, GetHost(pointer)); ! 366: /* ! 367: * If this USED to be a start field location, ! 368: * recompute the terminal attributes. ! 369: */ ! 370: if (termattr == UNDETERMINED) { ! 371: termattr = WhereTermAttrByte(pointer); ! 372: if ((termattr != 0) || TermIsStartField(0)) { ! 373: termattr = GetTerminal(termattr); ! 374: DoAttributes(termattr); ! 375: } else { /* Unformatted screen */ ! 376: termattr = NORMAL; ! 377: } ! 378: } ! 379: } ! 380: pointer = ScreenInc(pointer); ! 381: if (!(--columnsleft)) { ! 382: DoARefresh(); ! 383: EmptyTerminal(); ! 384: if (HaveInput) { /* if input came in, take it */ ! 385: int c, j; ! 386: ! 387: /* ! 388: * We need to start a new terminal field ! 389: * at this location iff the terminal attributes ! 390: * of this location are not what we have had ! 391: * them as (ie: we've overwritten the terminal ! 392: * start field, a the previous field had different ! 393: * display characteristics). ! 394: */ ! 395: ! 396: isattr = TermAttributes(pointer); ! 397: DoAttributes(isattr); ! 398: if ((!TermIsStartField(pointer)) && ! 399: (isattr != termattr)) { ! 400: /* ! 401: * Since we are going to leave a new field ! 402: * at this terminal position, we ! 403: * need to make sure that we get an actual ! 404: * non-highlighted blank on the screen. ! 405: */ ! 406: if ((is != DISP_BLANK) || (termattr&HIGHLIGHT)) { ! 407: SetHighlightMode(0); /* Turn off highlight */ ! 408: c = ScreenInc(pointer); ! 409: j = DISP_BLANK; ! 410: DoCharacterAt(j, c); ! 411: } ! 412: if (termattr&HIGHLIGHT) { ! 413: termattr = ATTR_DSPD_HIGH; ! 414: } else if (termattr&NONDISPLAY) { ! 415: termattr = ATTR_DSPD_NONDISPLAY; ! 416: } else { ! 417: termattr = 0; ! 418: } ! 419: TermNewField(pointer, termattr); ! 420: } ! 421: break; ! 422: } ! 423: move(ScreenLine(pointer), 0); ! 424: columnsleft = NumberColumns; ! 425: } ! 426: } /* end of for (;;) */ ! 427: } /* end of while (...) */ ! 428: } ! 429: DoARefresh(); ! 430: Lowest = pointer; ! 431: if (Lowest > Highest) { /* if we finished input... */ ! 432: Lowest = HighestScreen()+1; ! 433: Highest = LowestScreen()-1; ! 434: terminalCursorAddress = CorrectTerminalCursor(); ! 435: if (ERR == move(ScreenLine(terminalCursorAddress), ! 436: ScreenLineOffset(terminalCursorAddress))) { ! 437: GoAway("move", terminalCursorAddress); ! 438: } ! 439: DoARefresh(); ! 440: if (needToRing) { ! 441: StringToTerminal(bellSequence); ! 442: needToRing = 0; ! 443: } ! 444: } ! 445: EmptyTerminal(); /* move data along */ ! 446: return; ! 447: } ! 448: ! 449: #if defined(NOT43) ! 450: static int ! 451: #else /* defined(NOT43) */ ! 452: static void ! 453: #endif /* defined(NOT43) */ ! 454: FastScreen() ! 455: { ! 456: #if defined(MSDOS) ! 457: #define SaveCorner 0 ! 458: #else /* defined(MSDOS) */ ! 459: #define SaveCorner 1 ! 460: #endif /* defined(MSDOS) */ ! 461: ! 462: #define DoAttribute(a) if (IsHighlightedAttr(a)) { \ ! 463: standout(); \ ! 464: } else { \ ! 465: standend(); \ ! 466: } \ ! 467: if (IsNonDisplayAttr(a)) { \ ! 468: a = 0; /* zero == don't display */ \ ! 469: } \ ! 470: if (!FormattedScreen()) { \ ! 471: a = 1; /* one ==> do display on unformatted */\ ! 472: } ! 473: ScreenImage *p, *upper; ! 474: int fieldattr; /* spends most of its time == 0 or 1 */ ! 475: ! 476: /* OK. We want to do this a quickly as possible. So, we assume we ! 477: * only need to go from Lowest to Highest. However, if we find a ! 478: * field in the middle, we do the whole screen. ! 479: * ! 480: * In particular, we separate out the two cases from the beginning. ! 481: */ ! 482: if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) { ! 483: register int columnsleft; ! 484: ! 485: move(ScreenLine(Lowest), ScreenLineOffset(Lowest)); ! 486: p = &Host[Lowest]; ! 487: #if !defined(MSDOS) ! 488: if (Highest == HighestScreen()) { ! 489: Highest = ScreenDec(Highest); ! 490: } ! 491: #endif /* !defined(MSDOS) */ ! 492: upper = &Host[Highest]; ! 493: fieldattr = FieldAttributes(Lowest); ! 494: DoAttribute(fieldattr); /* Set standout, non-display status */ ! 495: columnsleft = NumberColumns-ScreenLineOffset(p-Host); ! 496: ! 497: while (p <= upper) { ! 498: if (IsStartFieldPointer(p)) { /* New field? */ ! 499: Highest = HighestScreen(); ! 500: Lowest = LowestScreen(); ! 501: FastScreen(); /* Recurse */ ! 502: return; ! 503: } else if (fieldattr) { /* Should we display? */ ! 504: /* Display translated data */ ! 505: addch((char)disp_asc[GetTerminalPointer(p)]); ! 506: } else { ! 507: addch(' '); /* Display a blank */ ! 508: } ! 509: /* If the physical screen is larger than what we ! 510: * are using, we need to make sure that each line ! 511: * starts at the beginning of the line. Otherwise, ! 512: * we will just string all the lines together. ! 513: */ ! 514: p++; ! 515: if (--columnsleft == 0) { ! 516: int i = p-Host; ! 517: ! 518: move(ScreenLine(i), 0); ! 519: columnsleft = NumberColumns; ! 520: } ! 521: } ! 522: } else { /* Going from Lowest to Highest */ ! 523: unsigned char tmpbuf[MAXNUMBERCOLUMNS+1]; ! 524: ScreenImage *End = &Host[ScreenSize]-1-SaveCorner; ! 525: register unsigned char *tmp = tmpbuf, *tmpend = tmpbuf+NumberColumns; ! 526: ! 527: *tmpend = 0; /* terminate from the beginning */ ! 528: move(0,0); ! 529: p = Host; ! 530: fieldattr = FieldAttributes(LowestScreen()); ! 531: DoAttribute(fieldattr); /* Set standout, non-display status */ ! 532: ! 533: while (p <= End) { ! 534: if (IsStartFieldPointer(p)) { /* New field? */ ! 535: if (tmp != tmpbuf) { ! 536: *tmp++ = 0; /* close out */ ! 537: addstr((char *)tmpbuf); ! 538: tmp = tmpbuf; ! 539: tmpend = tmpbuf+NumberColumns-ScreenLineOffset(p-Host)-1; ! 540: } ! 541: standend(); ! 542: addch(' '); ! 543: fieldattr = FieldAttributesPointer(p); /* Get attributes */ ! 544: DoAttribute(fieldattr); /* Set standout, non-display */ ! 545: } else { ! 546: if (fieldattr) { /* Should we display? */ ! 547: /* Display translated data */ ! 548: *tmp++ = disp_asc[GetTerminalPointer(p)]; ! 549: } else { ! 550: *tmp++ = ' '; ! 551: } ! 552: } ! 553: /* If the physical screen is larger than what we ! 554: * are using, we need to make sure that each line ! 555: * starts at the beginning of the line. Otherwise, ! 556: * we will just string all the lines together. ! 557: */ ! 558: p++; ! 559: if (tmp == tmpend) { ! 560: int i = p-Host; /* Be sure the "p++" happened first! */ ! 561: ! 562: *tmp++ = 0; ! 563: addstr((char *)tmpbuf); ! 564: tmp = tmpbuf; ! 565: move(ScreenLine(i), 0); ! 566: tmpend = tmpbuf + NumberColumns; ! 567: } ! 568: } ! 569: if (tmp != tmpbuf) { ! 570: *tmp++ = 0; ! 571: addstr((char *)tmpbuf); ! 572: tmp = tmpbuf; ! 573: } ! 574: } ! 575: Lowest = HighestScreen()+1; ! 576: Highest = LowestScreen()-1; ! 577: terminalCursorAddress = CorrectTerminalCursor(); ! 578: if (ERR == move(ScreenLine(terminalCursorAddress), ! 579: ScreenLineOffset(terminalCursorAddress))) { ! 580: GoAway("move", terminalCursorAddress); ! 581: } ! 582: DoARefresh(); ! 583: if (needToRing) { ! 584: StringToTerminal(bellSequence); ! 585: needToRing = 0; ! 586: } ! 587: EmptyTerminal(); /* move data along */ ! 588: return; ! 589: } ! 590: ! 591: ! 592: /* TryToSend - send data out to user's terminal */ ! 593: ! 594: #if defined(NOT43) ! 595: int ! 596: #else /* defined(NOT43) */ ! 597: void ! 598: #endif /* defined(NOT43) */ ! 599: (*TryToSend)() = FastScreen; ! 600: ! 601: /*ARGSUSED*/ ! 602: void ! 603: ScreenOIA(oia) ! 604: OIA *oia; ! 605: { ! 606: } ! 607: ! 608: ! 609: /* InitTerminal - called to initialize the screen, etc. */ ! 610: ! 611: void ! 612: InitTerminal() ! 613: { ! 614: #if defined(unix) ! 615: struct sgttyb ourttyb; ! 616: static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, ! 617: 2400, 4800, 9600 }; ! 618: #endif ! 619: extern void InitMapping(); ! 620: ! 621: InitMapping(); /* Go do mapping file (MAP3270) first */ ! 622: if (!screenInitd) { /* not initialized */ ! 623: #if defined(unix) ! 624: char KSEbuffer[2050]; ! 625: char *lotsofspace = KSEbuffer; ! 626: extern int abort(); ! 627: extern char *tgetstr(); ! 628: #endif /* defined(unix) */ ! 629: ! 630: if (initscr() == ERR) { /* Initialize curses to get line size */ ! 631: ExitString("InitTerminal: Error initializing curses", 1); ! 632: /*NOTREACHED*/ ! 633: } ! 634: MaxNumberLines = LINES; ! 635: MaxNumberColumns = COLS; ! 636: ClearArray(Terminal); ! 637: terminalCursorAddress = SetBufferAddress(0,0); ! 638: #if defined(unix) ! 639: signal(SIGHUP, abort); ! 640: #endif ! 641: ! 642: TryToSend = FastScreen; ! 643: #if defined(unix) ! 644: ioctl(1, TIOCGETP, (char *) &ourttyb); ! 645: if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) { ! 646: max_changes_before_poll = 1920; ! 647: } else { ! 648: max_changes_before_poll = speeds[ourttyb.sg_ospeed]/10; ! 649: if (max_changes_before_poll < 40) { ! 650: max_changes_before_poll = 40; ! 651: } ! 652: TryToSend = SlowScreen; ! 653: HaveInput = 1; /* get signals going */ ! 654: } ! 655: #endif /* defined(unix) */ ! 656: setcommandmode(); ! 657: /* ! 658: * By now, initscr() (in curses) has been called (from telnet.c), ! 659: * and the screen has been initialized. ! 660: */ ! 661: #if defined(unix) ! 662: nonl(); ! 663: /* the problem is that curses catches SIGTSTP to ! 664: * be nice, but it messes us up. ! 665: */ ! 666: signal(SIGTSTP, SIG_DFL); ! 667: if ((myKS = tgetstr("ks", &lotsofspace)) != 0) { ! 668: myKS = strsave(myKS); ! 669: StringToTerminal(myKS); ! 670: } ! 671: if ((myKE = tgetstr("ke", &lotsofspace)) != 0) { ! 672: myKE = strsave(myKE); ! 673: } ! 674: if (tgetstr("md", &lotsofspace) && tgetstr("me", &lotsofspace)) { ! 675: SO = strsave(tgetstr("md", &lotsofspace)); ! 676: SE = strsave(tgetstr("me", &lotsofspace)); ! 677: } ! 678: #endif ! 679: DoARefresh(); ! 680: setconnmode(); ! 681: if (VB && *VB) { ! 682: bellSequence = VB; /* use visual bell */ ! 683: } ! 684: screenInitd = 1; ! 685: screenStopped = 0; /* Not stopped */ ! 686: } ! 687: } ! 688: ! 689: ! 690: /* StopScreen - called when we are going away... */ ! 691: ! 692: void ! 693: StopScreen(doNewLine) ! 694: int doNewLine; ! 695: { ! 696: if (screenInitd && !screenStopped) { ! 697: move(NumberLines-1, 1); ! 698: standend(); ! 699: inHighlightMode = 0; ! 700: DoARefresh(); ! 701: setcommandmode(); ! 702: endwin(); ! 703: setconnmode(); ! 704: #if defined(unix) ! 705: if (myKE) { ! 706: StringToTerminal(myKE); ! 707: } ! 708: #endif /* defined(unix) */ ! 709: if (doNewLine) { ! 710: StringToTerminal("\r\n"); ! 711: } ! 712: EmptyTerminal(); ! 713: screenStopped = 1; /* This is stopped */ ! 714: } ! 715: } ! 716: ! 717: ! 718: /* RefreshScreen - called to cause the screen to be refreshed */ ! 719: ! 720: void ! 721: RefreshScreen() ! 722: { ! 723: clearok(curscr, TRUE); ! 724: (*TryToSend)(); ! 725: } ! 726: ! 727: ! 728: /* ConnectScreen - called to reconnect to the screen */ ! 729: ! 730: void ! 731: ConnectScreen() ! 732: { ! 733: if (screenInitd) { ! 734: #if defined(unix) ! 735: if (myKS) { ! 736: StringToTerminal(myKS); ! 737: } ! 738: #endif /* defined(unix) */ ! 739: RefreshScreen(); ! 740: (*TryToSend)(); ! 741: screenStopped = 0; ! 742: } ! 743: } ! 744: ! 745: /* LocalClearScreen() - clear the whole ball of wax, cheaply */ ! 746: ! 747: void ! 748: LocalClearScreen() ! 749: { ! 750: extern void Clear3270(); ! 751: ! 752: outputPurge(); /* flush all data to terminal */ ! 753: clear(); /* clear in curses */ ! 754: ClearArray(Terminal); ! 755: Clear3270(); ! 756: Lowest = HighestScreen()+1; /* everything in sync... */ ! 757: Highest = LowestScreen()+1; ! 758: } ! 759: ! 760: ! 761: void ! 762: BellOff() ! 763: { ! 764: if (bellwinup) { ! 765: delwin(bellwin); ! 766: bellwin = 0; ! 767: bellwinup = 0; ! 768: touchwin(stdscr); ! 769: DoARefresh(); ! 770: } ! 771: } ! 772: ! 773: ! 774: void ! 775: RingBell(s) ! 776: char *s; ! 777: { ! 778: needToRing = 1; ! 779: if (s) { ! 780: int len = strlen(s); ! 781: ! 782: if (len > COLS-2) { ! 783: len = COLS-2; ! 784: } ! 785: if ((bellwin = newwin(3, len+2, LINES/2, 0)) == NULL) { ! 786: OurExitString("Error from newwin in RingBell", 1); ! 787: } ! 788: werase(bellwin); ! 789: wstandout(bellwin); ! 790: box(bellwin, '|', '-'); ! 791: if (wmove(bellwin, 1, 1) == ERR) { ! 792: OurExitString("Error from wmove in RingBell", 1); ! 793: } ! 794: while (len--) { ! 795: if (waddch(bellwin, *s++) == ERR) { ! 796: OurExitString("Error from waddch in RingBell", 1); ! 797: } ! 798: } ! 799: wstandend(bellwin); ! 800: if (wrefresh(bellwin) == ERR) { ! 801: OurExitString("Error from wrefresh in RingBell", 1); ! 802: } ! 803: bellwinup = 1; ! 804: } ! 805: } ! 806: ! 807: ! 808: /* returns a 1 if no more output available (so, go ahead and block), ! 809: or a 0 if there is more output available (so, just poll the other ! 810: sources/destinations, don't block). ! 811: */ ! 812: ! 813: int ! 814: DoTerminalOutput() ! 815: { ! 816: /* called just before a select to conserve IO to terminal */ ! 817: if (!(screenInitd||screenStopped)) { ! 818: return 1; /* No output if not initialized */ ! 819: } ! 820: if ((Lowest <= Highest) || needToRing || ! 821: (terminalCursorAddress != CorrectTerminalCursor())) { ! 822: (*TryToSend)(); ! 823: } ! 824: if (Lowest > Highest) { ! 825: return 1; /* no more output now */ ! 826: } else { ! 827: return 0; /* more output for future */ ! 828: } ! 829: } ! 830: ! 831: /* ! 832: * The following are defined to handle transparent data. ! 833: */ ! 834: ! 835: void ! 836: TransStop() ! 837: { ! 838: #if defined(unix) ! 839: if (tcflag == 0) { ! 840: tcflag = -1; ! 841: (void) signal(SIGCHLD, SIG_DFL); ! 842: } else if (tcflag > 0) { ! 843: setcommandmode(); ! 844: (void) close(tin); ! 845: (void) close(tout); ! 846: tin = savefd[0]; ! 847: tout = savefd[1]; ! 848: setconnmode(); ! 849: tcflag = -1; ! 850: (void) signal(SIGCHLD, SIG_DFL); ! 851: } ! 852: #endif /* defined(unix) */ ! 853: RefreshScreen(); ! 854: } ! 855: ! 856: void ! 857: TransOut(buffer, count, kind, control) ! 858: unsigned char *buffer; ! 859: int count; ! 860: int kind; /* 0 or 5 */ ! 861: int control; /* To see if we are done */ ! 862: { ! 863: #if defined(unix) ! 864: extern char *transcom; ! 865: int inpipefd[2], outpipefd[2]; ! 866: void aborttc(); ! 867: #endif /* defined(unix) */ ! 868: ! 869: while (DoTerminalOutput() == 0) { ! 870: #if defined(unix) ! 871: HaveInput = 0; ! 872: #endif /* defined(unix) */ ! 873: } ! 874: #if defined(unix) ! 875: if (transcom && tcflag == -1) { ! 876: while (1) { /* go thru once */ ! 877: if (pipe(outpipefd) < 0) { ! 878: break; ! 879: } ! 880: if (pipe(inpipefd) < 0) { ! 881: break; ! 882: } ! 883: if ((tcflag = fork()) == 0) { ! 884: (void) close(outpipefd[1]); ! 885: (void) close(0); ! 886: if (dup(outpipefd[0]) < 0) { ! 887: exit(1); ! 888: } ! 889: (void) close(outpipefd[0]); ! 890: (void) close(inpipefd[0]); ! 891: (void) close(1); ! 892: if (dup(inpipefd[1]) < 0) { ! 893: exit(1); ! 894: } ! 895: (void) close(inpipefd[1]); ! 896: if (execl("/bin/csh", "csh", "-c", transcom, (char *) 0)) { ! 897: exit(1); ! 898: } ! 899: } ! 900: (void) close(inpipefd[1]); ! 901: (void) close(outpipefd[0]); ! 902: savefd[0] = tin; ! 903: savefd[1] = tout; ! 904: setcommandmode(); ! 905: tin = inpipefd[0]; ! 906: tout = outpipefd[1]; ! 907: (void) signal(SIGCHLD, (int (*)())aborttc); ! 908: setconnmode(); ! 909: tcflag = 1; ! 910: break; ! 911: } ! 912: if (tcflag < 1) { ! 913: tcflag = 0; ! 914: } ! 915: } ! 916: #endif /* defined(unix) */ ! 917: (void) DataToTerminal((char *)buffer, count); ! 918: if (control && (kind == 0)) { /* Send in AID byte */ ! 919: SendToIBM(); ! 920: } else { ! 921: extern void TransInput(); ! 922: ! 923: TransInput(1, kind); /* Go get some data */ ! 924: } ! 925: } ! 926: ! 927: ! 928: #if defined(unix) ! 929: static void ! 930: aborttc() ! 931: { ! 932: setcommandmode(); ! 933: (void) close(tin); ! 934: (void) close(tout); ! 935: tin = savefd[0]; ! 936: tout = savefd[1]; ! 937: setconnmode(); ! 938: tcflag = 0; ! 939: } ! 940: #endif /* defined(unix) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.