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: }

Defined functions

AddHost defined in line 215; used 6 times
Clear3270 defined in line 164; used 2 times
ConnectScreen defined in line 142; used 3 times
DataFromNetwork defined in line 525; used 2 times
DoARefresh defined in line 240; used 7 times
DoTerminalOutput defined in line 508; used 3 times
LocalClear3270 defined in line 176; used 1 times
OurExitString defined in line 188; used 4 times
RefreshScreen defined in line 155; used 3 times
RingBell defined in line 202; used 14 times
StartScreen defined in line 74; used 1 times
Stop3270 defined in line 118; used 6 times
TryToSend defined in line 250; 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 227; used 6 times
AddHostA defined in line 219; used 3 times
CorrectTerminalCursor defined in line 40; used 3 times
DoCharacterAt defined in line 275; used 5 times
Ensure defined in line 639; used 5 times
SetHighestLowest defined in line 42; used 7 times
SetHighlightMode defined in line 261; used 5 times
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2450
Valid CSS Valid XHTML 1.0 Strict