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

Defined functions

AddHost defined in line 219; used 6 times
Clear3270 defined in line 168; used 2 times
ConnectScreen defined in line 146; used 3 times
DataFromNetwork defined in line 529; used 2 times
DoARefresh defined in line 244; used 7 times
DoTerminalOutput defined in line 512; used 3 times
LocalClear3270 defined in line 180; used 1 times
OurExitString defined in line 192; used 4 times
RefreshScreen defined in line 159; used 3 times
RingBell defined in line 206; used 14 times
StartScreen defined in line 74; used 1 times
Stop3270 defined in line 122; used 6 times
TryToSend defined in line 254; used 4 times

Defined variables

Blanks defined in line 64; used 2 times
KE defined in line 62; used 3 times
KS defined in line 62; used 5 times
MAX_CHANGES_BEFORE_POLL defined in line 55; used 4 times
OutputClock defined in line 68; used 8 times
TransparentClock defined in line 69; used 7 times
bellSequence defined in line 59; used 2 times
needToRing defined in line 58; used 5 times
sccsid defined in line 35; never used
screenInitd defined in line 54; used 4 times
terminalCursorAddress defined in line 53; used 9 times

Defined macros

AddHost defined in line 231; used 6 times
AddHostA defined in line 223; used 3 times
CorrectTerminalCursor defined in line 40; used 3 times
DoCharacterAt defined in line 279; used 5 times
Ensure defined in line 643; used 5 times
SetHighestLowest defined in line 42; used 7 times
SetHighlightMode defined in line 265; used 5 times
Last modified: 1994-01-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5381
Valid CSS Valid XHTML 1.0 Strict