|
|
1.1 ! root 1: /* ! 2: * Copyright 1984, 1985 by the Regents of the University of ! 3: * California and by Gregory Glenn Minshall. ! 4: * ! 5: * Permission to use, copy, modify, and distribute these ! 6: * programs and their documentation for any purpose and ! 7: * without fee is hereby granted, provided that this ! 8: * copyright and permission appear on all copies and ! 9: * supporting documentation, the name of the Regents of ! 10: * the University of California not be used in advertising ! 11: * or publicity pertaining to distribution of the programs ! 12: * without specific prior permission, and notice be given in ! 13: * supporting documentation that copying and distribution is ! 14: * by permission of the Regents of the University of California ! 15: * and by Gregory Glenn Minshall. Neither the Regents of the ! 16: * University of California nor Gregory Glenn Minshall make ! 17: * representations about the suitability of this software ! 18: * for any purpose. It is provided "as is" without ! 19: * express or implied warranty. ! 20: */ ! 21: ! 22: ! 23: /* this exists to patch over DataFromNetwork until it is ready */ ! 24: ! 25: #include <signal.h> ! 26: #include <sgtty.h> ! 27: #include <stdio.h> ! 28: #include <curses.h> ! 29: ! 30: #include "ascebc.h" ! 31: #include "3270.h" ! 32: #include "screen.h" ! 33: ! 34: #ifndef lint ! 35: static char sccsid[] = "@(#)datastream.c 2.12\t12/16/85"; ! 36: #endif /* lint */ ! 37: ! 38: void EmptyTerminal(); ! 39: ! 40: #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? terminalCursorAddress:UnLocked? CursorAddress: HighestScreen()) ! 41: ! 42: #define SetHighestLowest(position) { \ ! 43: if (position < Lowest) { \ ! 44: Lowest = position; \ ! 45: } \ ! 46: if (position > Highest) { \ ! 47: Highest = position; \ ! 48: } \ ! 49: } ! 50: ! 51: extern char ebcasc[NEBCASC][NEBC]; /* translate table */ ! 52: ! 53: static int terminalCursorAddress; /* where the cursor is on term */ ! 54: static int screenInitd; /* the screen has been initialized */ ! 55: static int MAX_CHANGES_BEFORE_POLL; /* how many characters before looking */ ! 56: /* at terminal and net again */ ! 57: ! 58: static int needToRing = 0; /* need to ring terinal bell */ ! 59: static char *bellSequence = "\07"; /* bell sequence (may be replaced by ! 60: * VB during initialization) ! 61: */ ! 62: static char *KS, *KE; /* Turn on and off keyboard */ ! 63: ! 64: static char Blanks[sizeof Terminal]; /* lots of blanks */ ! 65: ! 66: /* some globals */ ! 67: ! 68: int OutputClock; /* what time it is */ ! 69: int TransparentClock; /* time we were last in transparent */ ! 70: ! 71: ! 72: /* StartScreen - called to initialize the screen, etc. */ ! 73: ! 74: StartScreen() ! 75: { ! 76: int save; ! 77: struct sgttyb ourttyb; ! 78: static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, ! 79: 2400, 4800, 9600 }; ! 80: static char KSEbuffer[2050]; ! 81: char *lotsofspace = KSEbuffer, *tgetstr(); ! 82: ! 83: if (!screenInitd) { ! 84: ioctl(1, TIOCGETP, (char *) &ourttyb); ! 85: if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) { ! 86: MAX_CHANGES_BEFORE_POLL = 1920; ! 87: } else { ! 88: MAX_CHANGES_BEFORE_POLL = speeds[ourttyb.sg_ospeed]/10; ! 89: if (MAX_CHANGES_BEFORE_POLL < 40) { ! 90: MAX_CHANGES_BEFORE_POLL = 40; ! 91: } ! 92: } ! 93: save = mode(0); ! 94: initscr(); /* start up curses */ ! 95: nonl(); ! 96: /* the problem is that curses catches SIGTSTP to ! 97: * be nice, but it messes us up. ! 98: */ ! 99: signal(SIGTSTP, SIG_DFL); ! 100: KS = tgetstr("ks", &lotsofspace); ! 101: KE = tgetstr("ke", &lotsofspace); ! 102: if (KS) { ! 103: StringToTerminal(KS); ! 104: } ! 105: DoARefresh(); ! 106: (void) mode(save); ! 107: if (VB && *VB) { ! 108: bellSequence = VB; /* use visual bell */ ! 109: } ! 110: screenInitd = 1; ! 111: } ! 112: } ! 113: ! 114: ! 115: ! 116: /* Stop3270 - called when we are going away... */ ! 117: ! 118: Stop3270(doNewLine) ! 119: int doNewLine; ! 120: { ! 121: if (screenInitd) { ! 122: int save; ! 123: ! 124: move(NUMBERLINES-1, 1); ! 125: DoARefresh(); ! 126: if (KE) { ! 127: StringToTerminal(KE); ! 128: } ! 129: if (doNewLine) { ! 130: StringToTerminal("\r\n"); ! 131: } ! 132: EmptyTerminal(); ! 133: save = mode(0); ! 134: endwin(); ! 135: (void) mode(save); ! 136: } ! 137: } ! 138: ! 139: ! 140: /* ConnectScreen - called to reconnect to the screen */ ! 141: ! 142: ConnectScreen() ! 143: { ! 144: if (screenInitd) { ! 145: if (KS) { ! 146: StringToTerminal(KS); ! 147: } ! 148: RefreshScreen(); ! 149: TryToSend(); ! 150: } ! 151: } ! 152: ! 153: /* RefreshScreen - called to cause the screen to be refreshed */ ! 154: ! 155: RefreshScreen() ! 156: { ! 157: clearok(curscr, TRUE); ! 158: TryToSend(); ! 159: } ! 160: ! 161: ! 162: /* Clear3270 - called to clear the screen */ ! 163: ! 164: Clear3270() ! 165: { ! 166: bzero((char *)Host, sizeof(Host)); ! 167: DeleteAllFields(); /* get rid of all fields */ ! 168: BufferAddress = SetBufferAddress(0,0); ! 169: CursorAddress = SetBufferAddress(0,0); ! 170: Lowest = LowestScreen(); ! 171: Highest = HighestScreen(); ! 172: } ! 173: ! 174: /* LocalClear3270() - clear the whole ball of wax, cheaply */ ! 175: ! 176: LocalClear3270() ! 177: { ! 178: outputPurge(); /* flush all data to terminal */ ! 179: clear(); /* clear in curses */ ! 180: bzero((char *)Terminal, sizeof Terminal); ! 181: Clear3270(); /* clear host part */ ! 182: Lowest = HighestScreen()+1; /* everything in sync... */ ! 183: Highest = LowestScreen()+1; ! 184: } ! 185: ! 186: /* OurExitString - designed to keep us from going through infinite recursion */ ! 187: ! 188: OurExitString(file, string, value) ! 189: FILE *file; ! 190: char *string; ! 191: int value; ! 192: { ! 193: static int recursion = 0; ! 194: ! 195: if (!recursion) { ! 196: recursion = 1; ! 197: ExitString(file, string, value); ! 198: } ! 199: } ! 200: ! 201: ! 202: RingBell() ! 203: { ! 204: needToRing = 1; ! 205: } ! 206: ! 207: /* AddHost - called to add a character to the buffer. ! 208: * We use a macro in this module, since we call it so ! 209: * often from loops. ! 210: * ! 211: * NOTE: It is a macro, so don't go around using AddHost(p, *c++), or ! 212: * anything similar. (I don't define any temporary variables, again ! 213: * just for the speed.) ! 214: */ ! 215: AddHost(position, character) ! 216: int position; ! 217: char character; ! 218: { ! 219: # define AddHostA(p,c) \ ! 220: { \ ! 221: if (IsStartField(p)) { \ ! 222: DeleteField(p); \ ! 223: SetHighestLowest(p); \ ! 224: } \ ! 225: SetHost(p, c); \ ! 226: } ! 227: # define AddHost(p,c) \ ! 228: { \ ! 229: AddHostA(p,c); \ ! 230: if ((c != GetTerminal(p)) || TermIsStartField(p)) { \ ! 231: SetHighestLowest(p); \ ! 232: } \ ! 233: } /* end of macro of AddHost */ ! 234: ! 235: AddHost(position, character); ! 236: } ! 237: ! 238: /* DoARefresh */ ! 239: ! 240: static ! 241: DoARefresh() ! 242: { ! 243: if (ERR == refresh()) { ! 244: OurExitString(stderr, "ERR from refresh\n", 1); ! 245: } ! 246: } ! 247: ! 248: /* TryToSend - send data out to user's terminal */ ! 249: ! 250: static ! 251: TryToSend() ! 252: { ! 253: register int pointer; ! 254: register int c; ! 255: register int fieldattr; ! 256: register int changes; ! 257: ! 258: static int inHighlightMode = 0; ! 259: extern int HaveInput; /* 1 if there is input to check out */ ! 260: ! 261: # define SetHighlightMode(p) { \ ! 262: if (!IsStartField(p) && IsHighlightedAttr(fieldattr)) { \ ! 263: if (!inHighlightMode) { \ ! 264: inHighlightMode = 1; \ ! 265: standout(); \ ! 266: } \ ! 267: } else { \ ! 268: if (inHighlightMode) { \ ! 269: inHighlightMode = 0; \ ! 270: standend(); \ ! 271: } \ ! 272: } \ ! 273: } ! 274: ! 275: # define DoCharacterAt(c,p) { \ ! 276: SetTerminal(p, c); \ ! 277: if (p != HighestScreen()) { \ ! 278: c = TerminalCharacterAttr(ebcasc[0][c&0xff], p, \ ! 279: fieldattr); \ ! 280: if (terminalCursorAddress != p) { \ ! 281: if (ERR == mvaddch(ScreenLine(p), \ ! 282: ScreenLineOffset(p), c)) {\ ! 283: char foo[100]; \ ! 284: \ ! 285: sprintf(foo, "ERR from mvaddch at %d (%d, %d)\n", \ ! 286: p, ScreenLine(p), ScreenLineOffset(p)); \ ! 287: OurExitString(stderr, foo, 1); \ ! 288: } \ ! 289: } else { \ ! 290: if (ERR == addch(c)) {\ ! 291: char foo[100]; \ ! 292: \ ! 293: sprintf(foo, "ERR from addch at %d (%d, %d)\n", \ ! 294: p, ScreenLine(p), ScreenLineOffset(p)); \ ! 295: OurExitString(stderr, foo, 1); \ ! 296: } \ ! 297: } \ ! 298: terminalCursorAddress = ScreenInc(p); \ ! 299: } \ ! 300: /* if (pointer%LINESIZE == LINESIZE-1) { \ ! 301: DoARefresh(); \ ! 302: if (TtyChars() > MAX_CHANGES_BEFORE_POLL) { \ ! 303: EmptyTerminal(); \ ! 304: } \ ! 305: } */ \ ! 306: } ! 307: ! 308: /* run through screen, printing out non-null lines */ ! 309: ! 310: /* There are two separate reasons for wanting to terminate this ! 311: * loop early. One is to respond to new input (either from ! 312: * the terminal or from the network [host]). For this reason, ! 313: * we expect to see 'HaveInput' come true when new input comes in. ! 314: * ! 315: * The second reason is a bit more difficult (for me) to understand. ! 316: * Basically, we don't want to get too far ahead of the characters that ! 317: * appear on the screen. Ideally, we would type out a few characters, ! 318: * wait until they appeared on the screen, then type out a few more. ! 319: * The reason for this is that the user, on seeing some characters ! 320: * appear on the screen may then start to type something. We would ! 321: * like to look at what the user types at about the same 'time' ! 322: * (measured by characters being sent to the terminal) that the ! 323: * user types them. For this reason, what we would like to do ! 324: * is update a bit, then call curses to do a refresh, flush the ! 325: * output to the terminal, then wait until the terminal data ! 326: * has been sent. ! 327: * ! 328: * Note that curses is useful for, among other things, deciding whether ! 329: * or not to send :ce: (clear to end of line), so we should call curses ! 330: * at end of lines (beginning of next lines). ! 331: * ! 332: * The problems here are the following: If we do lots of write(2)s, ! 333: * we will be doing lots of context switches, thus lots of overhead ! 334: * (which we have already). Second, if we do a select to wait for ! 335: * the output to drain, we have to contend with the fact that NOW ! 336: * we are scheduled to run, but who knows what the scheduler will ! 337: * decide when the output has caught up. ! 338: */ ! 339: ! 340: if (Highest == HighestScreen()) { ! 341: Highest = ScreenDec(Highest); /* else, while loop will never end */ ! 342: } ! 343: if (Lowest < LowestScreen()) { ! 344: Lowest = LowestScreen(); /* could be -1 in some cases with ! 345: * unformatted screens. ! 346: */ ! 347: } ! 348: if (Highest >= Lowest) { ! 349: /* if there is anything to do, do it. We won't terminate ! 350: * the loop until we've gone at least to Highest. ! 351: */ ! 352: pointer = Lowest; ! 353: while ((pointer <= Highest) && !HaveInput) { ! 354: ! 355: /* point at the next place of disagreement */ ! 356: pointer += (bunequal(Host+pointer, Terminal+pointer, ! 357: (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]); ! 358: ! 359: /* how many characters to change until the end of the ! 360: * current line ! 361: */ ! 362: changes = LINESIZE - ScreenLineOffset(pointer); ! 363: ! 364: /* what is the field attribute of the current position */ ! 365: fieldattr = FieldAttributes(WhereAttrByte(pointer)); ! 366: ! 367: if ((IsStartField(pointer) != TermIsStartField(pointer)) || ! 368: (IsStartField(pointer) && ! 369: fieldattr != TermAttributes(pointer))) { ! 370: ! 371: int oldterm; ! 372: ! 373: oldterm = TermAttributes(pointer); ! 374: if (IsStartField(pointer)) { ! 375: TermNewField(pointer, fieldattr); ! 376: SetTerminal(pointer, 0); ! 377: } else { ! 378: TermDeleteField(pointer); ! 379: } ! 380: /* We always do the first character in a divergent ! 381: * field, since otherwise the start of a field in ! 382: * the Host structure may leave a highlighted blank ! 383: * on the screen, and the start of a field in the ! 384: * Terminal structure may leave a non-highlighted ! 385: * something in the middle of a highlighted field ! 386: * on the screen. ! 387: */ ! 388: SetHighlightMode(pointer); ! 389: c = GetHost(pointer); ! 390: DoCharacterAt(c,pointer); ! 391: ! 392: if (NotVisuallyCompatibleAttributes ! 393: (pointer, fieldattr, oldterm)) { ! 394: int j; ! 395: ! 396: j = pointer; ! 397: ! 398: pointer = ScreenInc(pointer); ! 399: SetHighlightMode(pointer); /* Turn on highlighting */ ! 400: while (!IsStartField(pointer) && ! 401: !TermIsStartField(pointer)) { ! 402: c = GetHost(pointer); ! 403: DoCharacterAt(c,pointer); /* MACRO */ ! 404: pointer = ScreenInc(pointer); ! 405: if (!(--changes)) { ! 406: DoARefresh(); ! 407: EmptyTerminal(); ! 408: /* We don't look at HaveInput here, since ! 409: * if we leave this loop before the end of ! 410: * the 3270 field, we could have pointer ! 411: * higher than Highest. This would cause ! 412: * us to end the highest "while" loop, ! 413: * but we may, in fact, need to go around the ! 414: * screen once again. ! 415: */ ! 416: } ! 417: /* The loop needs to be protected ! 418: * from the situation where there had been only ! 419: * one field on the Terminal, and none on the Host. ! 420: * In this case, we have just deleted our last ! 421: * field. Hence, the break. ! 422: */ ! 423: if (j == pointer) { ! 424: break; ! 425: } ! 426: } ! 427: if (!TermIsStartField(pointer)) { ! 428: /* Remember what the terminal looked like */ ! 429: TermNewField(pointer, oldterm); ! 430: SetTerminal(pointer, 0); ! 431: /* The danger here is that the current position may ! 432: * be the start of a Host field. If so, and the field ! 433: * is highlighted, and our terminal was highlighted, ! 434: * then we will leave a highlighted blank at this ! 435: * position. ! 436: */ ! 437: SetHighlightMode(pointer); ! 438: c = 0; ! 439: DoCharacterAt(c,pointer); ! 440: } ! 441: /* We could be in the situation of needing to exit. ! 442: * This could happen if the current field wrapped around ! 443: * the end of the screen. ! 444: */ ! 445: if (j > pointer) { ! 446: break; ! 447: } ! 448: } else { ! 449: c = GetHost(pointer); ! 450: /* We always do the first character in a divergent ! 451: * field, since otherwise the start of a field in ! 452: * the Host structure may leave a highlighted blank ! 453: * on the screen, and the start of a field in the ! 454: * Terminal structure may leave a non-highlighted ! 455: * something in the middle of a highlighted field ! 456: * on the screen. ! 457: */ ! 458: SetHighlightMode(pointer); ! 459: DoCharacterAt(c,pointer); ! 460: } ! 461: } else { ! 462: SetHighlightMode(pointer); ! 463: /* The following will terminate at least when we get back ! 464: * to the original 'pointer' location (since we force ! 465: * things to be equal). ! 466: */ ! 467: while (((c = GetHost(pointer)) != GetTerminal(pointer)) && ! 468: !IsStartField(pointer) && !TermIsStartField(pointer)) { ! 469: DoCharacterAt(c, pointer); ! 470: pointer = ScreenInc(pointer); ! 471: if (!(--changes)) { ! 472: DoARefresh(); ! 473: EmptyTerminal(); ! 474: if (HaveInput) { /* if input came in, take it */ ! 475: break; ! 476: } ! 477: } ! 478: } ! 479: } ! 480: } ! 481: } ! 482: DoARefresh(); ! 483: Lowest = pointer; ! 484: if (Lowest > Highest) { /* if we finished input... */ ! 485: Lowest = HighestScreen()+1; ! 486: Highest = LowestScreen()-1; ! 487: terminalCursorAddress = CorrectTerminalCursor(); ! 488: if (ERR == move(ScreenLine(terminalCursorAddress), ! 489: ScreenLineOffset(terminalCursorAddress))) { ! 490: OurExitString(stderr, "ERR from move\n", 1); ! 491: } ! 492: DoARefresh(); ! 493: if (needToRing) { ! 494: StringToTerminal(bellSequence); ! 495: needToRing = 0; ! 496: } ! 497: } ! 498: EmptyTerminal(); /* move data along */ ! 499: return; ! 500: } ! 501: ! 502: ! 503: /* returns a 1 if no more output available (so, go ahead and block), ! 504: or a 0 if there is more output available (so, just poll the other ! 505: sources/destinations, don't block). ! 506: */ ! 507: ! 508: int ! 509: DoTerminalOutput() ! 510: { ! 511: /* called just before a select to conserve IO to terminal */ ! 512: if (Initialized && ! 513: ((Lowest <= Highest) || needToRing || ! 514: (terminalCursorAddress != CorrectTerminalCursor()))) { ! 515: TryToSend(); ! 516: } ! 517: if (Lowest > Highest) { ! 518: return(1); /* no more output now */ ! 519: } else { ! 520: return(0); /* more output for future */ ! 521: } ! 522: } ! 523: ! 524: /* returns the number of characters consumed */ ! 525: int ! 526: DataFromNetwork(buffer, count, control) ! 527: register char *buffer; /* what the data is */ ! 528: register int count; /* and how much there is */ ! 529: int control; /* this buffer terminated block */ ! 530: { ! 531: int origCount; ! 532: register int c; ! 533: register int i; ! 534: static int Command; ! 535: static int Wcc; ! 536: static int LastWasTerminated = 0; /* was "control" = 1 last time? */ ! 537: ! 538: if (!Initialized) { /* not initialized */ ! 539: int abort(); ! 540: ! 541: bzero((char *)Host, sizeof Host); ! 542: DeleteAllFields(); ! 543: for (i = 0; i < sizeof Blanks; i++) { ! 544: Blanks[i] = ' '; ! 545: } ! 546: bzero((char *)Terminal, sizeof Terminal); ! 547: Lowest = HighestScreen()+1; ! 548: Highest = LowestScreen()-1; ! 549: terminalCursorAddress = ! 550: CursorAddress = ! 551: BufferAddress = SetBufferAddress(0,0); ! 552: UnLocked = 1; ! 553: StartScreen(); ! 554: LastWasTerminated = 1; ! 555: Initialized = 1; ! 556: OutputClock = 1; ! 557: TransparentClock = -1; ! 558: signal(SIGHUP, abort); ! 559: } ! 560: ! 561: origCount = count; ! 562: ! 563: if (LastWasTerminated) { ! 564: ! 565: if (count < 2) { ! 566: if (count == 0) { ! 567: StringToTerminal("Short count received from host!\n"); ! 568: return(count); ! 569: } ! 570: Command = buffer[0]&0xff; ! 571: switch (Command) { /* This had better be a read command */ ! 572: case CMD_READ_MODIFIED: ! 573: DoReadModified(); ! 574: break; ! 575: case CMD_READ_BUFFER: ! 576: DoReadBuffer(); ! 577: break; ! 578: default: ! 579: break; ! 580: } ! 581: return(1); /* We consumed everything */ ! 582: } ! 583: Command = buffer[0]&0xff; ! 584: Wcc = buffer[1]&0xff; ! 585: if (Wcc & WCC_RESET_MDT) { ! 586: i = c = WhereAttrByte(LowestScreen()); ! 587: do { ! 588: if (HasMdt(i)) { ! 589: TurnOffMdt(i); ! 590: } ! 591: i = FieldInc(i); ! 592: } while (i != c); ! 593: } ! 594: ! 595: switch (Command) { ! 596: case CMD_ERASE_WRITE: ! 597: Clear3270(); ! 598: if (TransparentClock == OutputClock) { ! 599: clearok(curscr, TRUE); ! 600: } ! 601: break; ! 602: case CMD_ERASE_ALL_UNPROTECTED: ! 603: CursorAddress = HighestScreen()+1; ! 604: for (i = LowestScreen(); i <= HighestScreen(); ScreenInc(i)) { ! 605: if (IsUnProtected(i)) { ! 606: if (CursorAddress > i) { ! 607: CursorAddress = i; ! 608: } ! 609: AddHost(i, '\0'); ! 610: } ! 611: if (HasMdt(i)) { ! 612: TurnOffMdt(i); ! 613: } ! 614: } ! 615: if (CursorAddress == HighestScreen()+1) { ! 616: CursorAddress = SetBufferAddress(0,0); ! 617: } ! 618: UnLocked = 1; ! 619: AidByte = 0; ! 620: break; ! 621: case CMD_WRITE: ! 622: break; ! 623: default: ! 624: break; ! 625: } ! 626: ! 627: count -= 2; /* strip off command and wcc */ ! 628: buffer += 2; ! 629: ! 630: } ! 631: LastWasTerminated = 0; /* then, reset at end... */ ! 632: ! 633: while (count) { ! 634: count--; ! 635: c = (*buffer++)&0xff; ! 636: if (IsOrder(c)) { ! 637: /* handle an order */ ! 638: switch (c) { ! 639: # define Ensure(x) if (count < x) { \ ! 640: if (!control) { \ ! 641: return(origCount-(count+1)); \ ! 642: } else { \ ! 643: /* XXX - should not occur */ \ ! 644: count = 0; \ ! 645: break; \ ! 646: } \ ! 647: } ! 648: case ORDER_SF: ! 649: Ensure(1); ! 650: c = (*buffer++)&0xff; ! 651: count--; ! 652: if ( ! (IsStartField(BufferAddress) && ! 653: FieldAttributes(BufferAddress) == c)) { ! 654: if (NotVisuallyCompatibleAttributes(BufferAddress, c, ! 655: FieldAttributes(BufferAddress))) { ! 656: SetHighestLowest(BufferAddress); ! 657: } ! 658: if (GetTerminal(BufferAddress)) { ! 659: SetHighestLowest(BufferAddress); ! 660: } ! 661: NewField(BufferAddress,c); ! 662: } ! 663: SetHost(BufferAddress, 0); ! 664: BufferAddress = ScreenInc(BufferAddress); ! 665: break; ! 666: case ORDER_SBA: ! 667: Ensure(2); ! 668: i = buffer[0]; ! 669: c = buffer[1]; ! 670: if (!i && !c) { /* transparent write */ ! 671: if (!control) { ! 672: return(origCount-(count+1)); ! 673: } else { ! 674: while (Initialized && ! 675: ((Lowest <= Highest) || needToRing || ! 676: (terminalCursorAddress != ! 677: CorrectTerminalCursor()))) { ! 678: extern int HaveInput; ! 679: ! 680: HaveInput = 0; ! 681: TryToSend(); ! 682: } ! 683: if (TransparentClock != OutputClock) { ! 684: if (!DoTerminalOutput()) { ! 685: return(origCount-(count+1)); ! 686: } ! 687: move(ScreenLine(CursorAddress), ! 688: ScreenLineOffset(CursorAddress)); ! 689: DoARefresh(); ! 690: } ! 691: TransparentClock = OutputClock; /* this clock */ ! 692: (void) DataToTerminal(buffer+2, count-2); ! 693: SendToIBM(); ! 694: TransparentClock = OutputClock+1; /* clock next */ ! 695: buffer += count; ! 696: count -= count; ! 697: } ! 698: } else { ! 699: BufferAddress = Addr3270(i, c); ! 700: buffer += 2; ! 701: count -= 2; ! 702: } ! 703: break; ! 704: case ORDER_IC: ! 705: CursorAddress = BufferAddress; ! 706: break; ! 707: case ORDER_PT: ! 708: for (i = ScreenInc(BufferAddress); (i != HighestScreen()); ! 709: i = ScreenInc(i)) { ! 710: if (IsStartField(i)) { ! 711: i = ScreenInc(i); ! 712: if (!IsProtected(ScreenInc(i))) { ! 713: break; ! 714: } ! 715: if (i == HighestScreen()) { ! 716: break; ! 717: } ! 718: } ! 719: } ! 720: CursorAddress = i; ! 721: break; ! 722: case ORDER_RA: ! 723: Ensure(2); ! 724: i = Addr3270(buffer[0], buffer[1]); ! 725: c = buffer[2]; ! 726: do { ! 727: AddHost(BufferAddress, c); ! 728: BufferAddress = ScreenInc(BufferAddress); ! 729: } while (BufferAddress != i); ! 730: buffer += 3; ! 731: count -= 3; ! 732: break; ! 733: case ORDER_EUA: /* (from [here,there), ie: half open interval] */ ! 734: Ensure(2); ! 735: c = FieldAttributes(WhereAttrByte(BufferAddress)); ! 736: for (i = Addr3270(buffer[0], buffer[1]); i != BufferAddress; ! 737: BufferAddress = ScreenInc(BufferAddress)) { ! 738: if (!IsProtectedAttr(BufferAddress, c)) { ! 739: AddHost(BufferAddress, 0); ! 740: } ! 741: } ! 742: buffer += 2; ! 743: count -= 2; ! 744: break; ! 745: case ORDER_YALE: /* special YALE defined order */ ! 746: Ensure(2); /* need at least two characters */ ! 747: if ((*buffer&0xff) == 0x5b) { ! 748: i = OptOrder(buffer+1, count-1, control); ! 749: if (i == 0) { ! 750: return(origCount-(count+1)); /* come here again */ ! 751: } else { ! 752: buffer += 1 + i; ! 753: count - = (1 + i); ! 754: } ! 755: } ! 756: break; ! 757: default: ! 758: break; /* XXX ? */ ! 759: } ! 760: if (count < 0) { ! 761: count = 0; ! 762: } ! 763: } else { ! 764: /* Data comes in large clumps - take it all */ ! 765: i = BufferAddress; ! 766: #ifdef NOTDEF ! 767: AddHost(i, c); ! 768: #else /* NOTDEF */ ! 769: AddHostA(i, c); ! 770: SetHighestLowest(i); ! 771: #endif /* NOTDEF */ ! 772: i = ScreenInc(i); ! 773: while (count && !IsOrder(c = *(buffer)&0xff)) { ! 774: buffer++; ! 775: #ifdef NOTDEF ! 776: AddHost(i, c); ! 777: #else /* NOTDEF */ ! 778: AddHostA(i, c); ! 779: #endif /* NOTDEF */ ! 780: i = ScreenInc(i); ! 781: #ifndef NOTDEF ! 782: if (i == LowestScreen()) { ! 783: SetHighestLowest(HighestScreen()); ! 784: } ! 785: #endif /* NOTDEF */ ! 786: count--; ! 787: } ! 788: #ifndef NOTDEF ! 789: SetHighestLowest(i); ! 790: #endif /* NOTDEF */ ! 791: BufferAddress = i; ! 792: } ! 793: } ! 794: if (count == 0) { ! 795: OutputClock++; /* time rolls on */ ! 796: if (control) { ! 797: if (Wcc & WCC_RESTORE) { ! 798: if (TransparentClock != OutputClock) { ! 799: AidByte = 0; ! 800: } ! 801: UnLocked = 1; ! 802: (void) TerminalIn(); /* move along user's input */ ! 803: } ! 804: if (Wcc & WCC_ALARM) { ! 805: RingBell(); ! 806: } ! 807: } ! 808: LastWasTerminated = control; /* state for next time */ ! 809: return(origCount); ! 810: } else { ! 811: return(origCount-count); ! 812: } ! 813: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.