Annotation of 43BSD/ucb/tn3270/datastream.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.