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