# 2.11BSD#431 - /usr/src/ucb/tn3270/datastream.c

##### Functions

    AddHost           X
    Clear3270         X
    ConnectScreen     X
    DataFromNetwork   X
    DoTerminalOutput  X
    LocalClear3270    X
    OurExitString     X
    RefreshScreen     X
    RingBell          X
    StartScreen       X
    Stop3270          X

##### Variables

    OutputClock       X
    TransparentClock  X

##### Macros

    AddHost           X
    AddHostA          X
    CorrectTerminalCursorX
    DoCharacterAt     X
    Ensure            X
    SetHighestLowest  X
    SetHighlightMode  X

       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

- in /usr/src/ucb/tn3270/keyboard.c line 111, 147-149(2), 427-431(2), 662

Clear3270 defined in line 168; used 2 times

- in line 185, 601

ConnectScreen defined in line 146; used 3 times

- in /usr/src/ucb/tn3270/keyboard.c line 488, 735, 741

DataFromNetwork defined in line 529; used 2 times

- in /usr/src/ucb/tn3270/tn3270.c line 664, 821

DoARefresh defined in line 244; used 7 times

- in line 109, 129, 410, 476, 486, 496, 693

DoTerminalOutput defined in line 512; used 3 times

- in line 688
- in /usr/src/ucb/tn3270/keyboard.c line 726
- in /usr/src/ucb/tn3270/tn3270.c line 506

LocalClear3270 defined in line 180; used 1 times

- in /usr/src/ucb/tn3270/keyboard.c line 512

OurExitString defined in line 192; used 4 times

- in line 248, 291, 299, 494

RefreshScreen defined in line 159; used 3 times

- in line 152
- in /usr/src/ucb/tn3270/keyboard.c line 575, 745

RingBell defined in line 206; used 14 times

- in line 809
- in /usr/src/ucb/tn3270/keyboard.c line 106, 414, 422, 527, 538, 561, 596, 693, 701, 873
- in /usr/src/ucb/tn3270/termin.c line 66, 140, 156

StartScreen defined in line 74; used 1 times

- in line 557

Stop3270 defined in line 122; used 6 times

- in /usr/src/ucb/tn3270/keyboard.c line 486, 733, 739
- in /usr/src/ucb/tn3270/tn3270.c line 276, 1033, 1362

TryToSend defined in line 254; used 4 times

- in line 153, 162, 519, 685

#### Defined variables

Blanks defined in line 64; used 2 times

- in line 547-548(2)

KE defined in line 62; used 3 times

- in line 105, 130-131(2)

KS defined in line 62; used 5 times

- in line 104-107(3), 149-150(2)

MAX_CHANGES_BEFORE_POLL defined in line 55; used 4 times

- in line 90-94(4)

OutputClock defined in line 68; used 8 times

- in line 40, 560, 602, 687, 695-698(2), 799-802(2)

TransparentClock defined in line 69; used 7 times

- in line 40, 561, 602, 687, 695-698(2), 802

bellSequence defined in line 59; used 2 times

- in line 112, 498

needToRing defined in line 58; used 5 times

- in line 208, 497-499(2), 517, 679

sccsid defined in line 35; never used
screenInitd defined in line 54; used 4 times

- in line 87, 114, 125, 148

terminalCursorAddress defined in line 53; used 9 times

- in line 40, 284, 302, 491-493(3), 518, 553, 680

#### Defined macros

AddHost defined in line 231; used 6 times

- in line 239, 613, 731, 743, 771, 780

AddHostA defined in line 223; used 3 times

- in line 233, 773, 782

CorrectTerminalCursor defined in line 40; used 3 times

- in line 491, 518, 681

DoCharacterAt defined in line 279; used 5 times

- in line 394, 407, 443, 463, 473

Ensure defined in line 643; used 5 times

- in line 653, 671, 727, 738, 750

SetHighestLowest defined in line 42; used 7 times

- in line 227, 235, 660-663(2), 774, 787, 793

SetHighlightMode defined in line 265; used 5 times

- in line 392, 403, 441, 462-466(2)

Last modified: 1994-01-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2813 |