Annotation of 43BSD/ucb/tn3270/datastream.c, revision 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.