Annotation of 43BSDTahoe/ucb/tn3270/sys_curses/termout.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that this notice is preserved and that due credit is given
                      7:  * to the University of California at Berkeley. The name of the University
                      8:  * may not be used to endorse or promote products derived from this
                      9:  * software without specific prior written permission. This software
                     10:  * is provided ``as is'' without express or implied warranty.
                     11:  */
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)termout.c  3.3 (Berkeley) 3/31/88";
                     15: #endif /* not lint */
                     16: 
                     17: #if defined(unix)
                     18: #include <signal.h>
                     19: #include <sgtty.h>
                     20: #endif
                     21: #include <stdio.h>
                     22: #include <curses.h>
                     23: 
                     24: #include "../general/general.h"
                     25: 
                     26: #include "terminal.h"
                     27: 
                     28: #include "../telnet.ext"
                     29: 
                     30: #include "../api/disp_asc.h"
                     31: 
                     32: #include "../ctlr/hostctlr.h"
                     33: #include "../ctlr/inbound.ext"
                     34: #include "../ctlr/oia.h"
                     35: #include "../ctlr/options.ext"
                     36: #include "../ctlr/outbound.ext"
                     37: #include "../ctlr/screen.h"
                     38: 
                     39: #include "../ascii/map3270.ext"
                     40: 
                     41: #include "../general/globals.h"
                     42: 
                     43: extern void EmptyTerminal();
                     44: 
                     45: #define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
                     46:                CursorAddress:UnLocked? CursorAddress: HighestScreen())
                     47: 
                     48: 
                     49: static int terminalCursorAddress;      /* where the cursor is on term */
                     50: static int screenInitd;                /* the screen has been initialized */
                     51: static int screenStopped;              /* the screen has been stopped */
                     52: static int max_changes_before_poll;    /* how many characters before looking */
                     53:                                        /* at terminal and net again */
                     54: 
                     55: static int needToRing;                 /* need to ring terinal bell */
                     56: static char *bellSequence = "\07";     /* bell sequence (may be replaced by
                     57:                                         * VB during initialization)
                     58:                                         */
                     59: static WINDOW *bellwin = 0;            /* The window the bell message is in */
                     60: int    bellwinup = 0;                  /* Are we up with it or not */
                     61: 
                     62: #if    defined(unix)
                     63: static char *KS, *KE;
                     64: #endif /* defined(unix) */
                     65: 
                     66: 
                     67: static int inHighlightMode = 0;
                     68: ScreenImage Terminal[MAXSCREENSIZE];
                     69: 
                     70: /* Variables for transparent mode */
                     71: #if    defined(unix)
                     72: static int tcflag = -1;                        /* transparent mode command flag */
                     73: static int savefd[2];                  /* for storing fds during transcom */
                     74: extern int     tin, tout;              /* file descriptors */
                     75: #endif /* defined(unix) */
                     76: 
                     77: 
                     78: /*
                     79:  * init_screen()
                     80:  *
                     81:  * Initialize variables used by screen.
                     82:  */
                     83: 
                     84: void
                     85: init_screen()
                     86: {
                     87:     bellwinup = 0;
                     88:     inHighlightMode = 0;
                     89:     ClearArray(Terminal);
                     90: }
                     91: 
                     92: 
                     93: /* OurExitString - designed to keep us from going through infinite recursion */
                     94: 
                     95: static void
                     96: OurExitString(file, string, value)
                     97: FILE   *file;
                     98: char   *string;
                     99: int    value;
                    100: {
                    101:     static int recursion = 0;
                    102: 
                    103:     if (!recursion) {
                    104:        recursion = 1;
                    105:        ExitString(file, string, value);
                    106:     }
                    107: }
                    108: 
                    109: 
                    110: /* DoARefresh */
                    111: 
                    112: static void
                    113: DoARefresh()
                    114: {
                    115:     if (ERR == refresh()) {
                    116:        OurExitString(stderr, "ERR from refresh\n", 1);
                    117:     }
                    118: }
                    119: 
                    120: static void
                    121: GoAway(from, where)
                    122: char *from;            /* routine that gave error */
                    123: int    where;          /* cursor address */
                    124: {
                    125:        char foo[100];
                    126: 
                    127:        sprintf(foo, "ERR from %s at %d (%d, %d)\n",
                    128:                from, where, ScreenLine(where), ScreenLineOffset(where));
                    129:        OurExitString(stderr, foo, 1);
                    130:        /* NOTREACHED */
                    131: }
                    132: 
                    133: /* What is the screen address of the attribute byte for the terminal */
                    134: 
                    135: static int
                    136: WhereTermAttrByte(p)
                    137: register int   p;
                    138: {
                    139:     register int i;
                    140: 
                    141:     i = p;
                    142: 
                    143:     do {
                    144:        if (TermIsStartField(i)) {
                    145:            return(i);
                    146:        }
                    147:        i = ScreenDec(i);
                    148:     } while (i != p);
                    149: 
                    150:     return(LowestScreen());    /* unformatted screen... */
                    151: }
                    152: 
                    153: /*
                    154:  *     There are two algorithms for updating the screen.
                    155:  *  The first, SlowScreen() optimizes the line between the
                    156:  *  computer and the screen (say a 9600 baud line).  To do
                    157:  *  this, we break out of the loop every so often to look
                    158:  *  at any pending input from the network (so that successive
                    159:  *  screens will only partially print until the final screen,
                    160:  *  the one the user possibly wants to see, is displayed
                    161:  *  in its entirety).
                    162:  *
                    163:  *     The second algorithm tries to optimize CPU time (by
                    164:  *  being simpler) at the cost of the bandwidth to the
                    165:  *  screen.
                    166:  *
                    167:  *     Of course, curses(3X) gets in here also.
                    168:  */
                    169: 
                    170: 
                    171: #if    defined(NOT43)
                    172: static int
                    173: #else  /* defined(NOT43) */
                    174: static void
                    175: #endif /* defined(NOT43) */
                    176: SlowScreen()
                    177: {
                    178:     register int pointer;
                    179:     register int c;
                    180:     register int fieldattr;
                    181:     register int columnsleft;
                    182: 
                    183: #   define  SetHighlightMode(p) { \
                    184:                if (!IsStartField(p) && IsHighlightedAttr(fieldattr)) { \
                    185:                    if (!inHighlightMode) { \
                    186:                        inHighlightMode = 1; \
                    187:                        standout(); \
                    188:                    } \
                    189:                } else { \
                    190:                    if (inHighlightMode) { \
                    191:                        inHighlightMode = 0; \
                    192:                        standend(); \
                    193:                    } \
                    194:                } \
                    195:            }
                    196: 
                    197: #   define  DoCharacterAt(c,p) { \
                    198:                SetTerminal(p, c); \
                    199:                if (p != HighestScreen()) { \
                    200:                    c = TerminalCharacterAttr(disp_asc[c&0xff], p, \
                    201:                                                                fieldattr); \
                    202:                    if (terminalCursorAddress != p) { \
                    203:                        if (ERR == mvaddch(ScreenLine(p), \
                    204:                                                ScreenLineOffset(p), c)) {\
                    205:                            GoAway("mvaddch", p); \
                    206:                        } \
                    207:                    } else { \
                    208:                        if (ERR == addch(c)) {\
                    209:                            GoAway("addch", p); \
                    210:                        } \
                    211:                    } \
                    212:                    terminalCursorAddress = ScreenInc(p); \
                    213:                } \
                    214:            }
                    215: 
                    216: 
                    217:     /* run through screen, printing out non-null lines */
                    218: 
                    219:     /* There are two separate reasons for wanting to terminate this
                    220:      * loop early.  One is to respond to new input (either from
                    221:      * the terminal or from the network [host]).  For this reason,
                    222:      * we expect to see 'HaveInput' come true when new input comes in.
                    223:      *
                    224:      * The second reason is a bit more difficult (for me) to understand.
                    225:      * Basically, we don't want to get too far ahead of the characters that
                    226:      * appear on the screen.  Ideally, we would type out a few characters,
                    227:      * wait until they appeared on the screen, then type out a few more.
                    228:      * The reason for this is that the user, on seeing some characters
                    229:      * appear on the screen may then start to type something.  We would
                    230:      * like to look at what the user types at about the same 'time'
                    231:      * (measured by characters being sent to the terminal) that the
                    232:      * user types them.  For this reason, what we would like to do
                    233:      * is update a bit, then call curses to do a refresh, flush the
                    234:      * output to the terminal, then wait until the terminal data
                    235:      * has been sent.
                    236:      *
                    237:      * Note that curses is useful for, among other things, deciding whether
                    238:      * or not to send :ce: (clear to end of line), so we should call curses
                    239:      * at end of lines (beginning of next lines).
                    240:      *
                    241:      * The problems here are the following:  If we do lots of write(2)s,
                    242:      * we will be doing lots of context switches, thus lots of overhead
                    243:      * (which we have already).  Second, if we do a select to wait for
                    244:      * the output to drain, we have to contend with the fact that NOW
                    245:      * we are scheduled to run, but who knows what the scheduler will
                    246:      * decide when the output has caught up.
                    247:      */
                    248: 
                    249:     if (Highest >= HighestScreen()) {  /* Could be > if screen shrunk... */
                    250:        Highest = ScreenDec(Highest);   /* else, while loop will never end */
                    251:     }
                    252:     if (Lowest < LowestScreen()) {
                    253:        Lowest = LowestScreen();        /* could be -1 in some cases with
                    254:                                         * unformatted screens.
                    255:                                         */
                    256:     }
                    257:     if (Highest >= (pointer = Lowest)) {
                    258:                /* if there is anything to do, do it.  We won't terminate
                    259:                 * the loop until we've gone at least to Highest.
                    260:                 */
                    261:        while ((pointer <= Highest) && !HaveInput) {
                    262: 
                    263:                /* point at the next place of disagreement */
                    264:            pointer += (bunequal(Host+pointer, Terminal+pointer,
                    265:                        (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]);
                    266: 
                    267:                /* how many characters to change until the end of the
                    268:                 * current line
                    269:                 */
                    270:            columnsleft = NumberColumns - ScreenLineOffset(pointer);
                    271:                /*
                    272:                 * Make sure we are where we think we are.
                    273:                 */
                    274:            move(ScreenLine(pointer), ScreenLineOffset(pointer));
                    275: 
                    276:                /* what is the field attribute of the current position */
                    277:            fieldattr = FieldAttributes(WhereAttrByte(pointer));
                    278: 
                    279:            if ((IsStartField(pointer) != TermIsStartField(pointer)) ||
                    280:                    (IsStartField(pointer) &&
                    281:                        fieldattr != TermAttributes(pointer))) {
                    282: 
                    283:                int oldterm;
                    284: 
                    285:                oldterm = TermAttributes(pointer);
                    286:                if (IsStartField(pointer)) {
                    287:                    TermNewField(pointer, fieldattr);
                    288:                    SetTerminal(pointer, 0);
                    289:                } else {
                    290:                    TermDeleteField(pointer);
                    291:                }
                    292:                    /* We always do the first character in a divergent
                    293:                     * field, since otherwise the start of a field in
                    294:                     * the Host structure may leave a highlighted blank
                    295:                     * on the screen, and the start of a field in the
                    296:                     * Terminal structure may leave a non-highlighted
                    297:                     * something in the middle of a highlighted field
                    298:                     * on the screen.
                    299:                     */
                    300:                SetHighlightMode(pointer);
                    301:                c = GetHost(pointer);
                    302:                DoCharacterAt(c,pointer);               /* MACRO */
                    303: 
                    304:                if (NotVisuallyCompatibleAttributes
                    305:                                (pointer, fieldattr, oldterm)) {
                    306:                    int j;
                    307: 
                    308:                    j = pointer;
                    309: 
                    310:                    pointer = ScreenInc(pointer);
                    311:                    if (!(--columnsleft)) {
                    312:                        DoARefresh();
                    313:                        EmptyTerminal();
                    314:                        move(ScreenLine(pointer), 0);
                    315:                        columnsleft = NumberColumns;
                    316:                    }
                    317:                    SetHighlightMode(pointer);  /* Turn on highlighting */
                    318:                    while ((!IsStartField(pointer)) &&
                    319:                                (!TermIsStartField(pointer))) {
                    320:                        c = GetHost(pointer);
                    321:                        DoCharacterAt(c,pointer);       /* MACRO */
                    322:                        pointer = ScreenInc(pointer);
                    323:                        if (!(--columnsleft)) {
                    324:                            DoARefresh();
                    325:                            EmptyTerminal();
                    326:                            move(ScreenLine(pointer), 0);
                    327:                            columnsleft = NumberColumns;
                    328:                                /* We don't look at HaveInput here, since
                    329:                                 * if we leave this loop before the end of
                    330:                                 * the 3270 field, we could have pointer
                    331:                                 * higher than Highest.  This would cause
                    332:                                 * us to end the highest "while" loop,
                    333:                                 * but we may, in fact, need to go around the
                    334:                                 * screen once again.
                    335:                                 */
                    336:                        }
                    337:                        /*              The loop needs to be protected
                    338:                         *      from the situation where there had been only
                    339:                         *      one field on the Terminal, and none on the Host.
                    340:                         *      In this case, we have just deleted our last
                    341:                         *      field.  Hence, the break.
                    342:                         */
                    343:                        if (j == pointer) {
                    344:                            break;
                    345:                        }
                    346:                    }
                    347:                    if (IsStartField(pointer) && !TermIsStartField(pointer)) {
                    348:                            /* Remember what the terminal looked like */
                    349:                        TermNewField(pointer, oldterm);
                    350:                            /*
                    351:                             * The danger here is that the current position may
                    352:                             * be the start of a Host field.  If so, and the
                    353:                             * field is highlighted, and our terminal was
                    354:                             * highlighted, then we will leave a highlighted
                    355:                             * blank at this position.
                    356:                             */
                    357:                        SetHighlightMode(pointer);
                    358:                        c = GetHost(pointer);
                    359:                        DoCharacterAt(c,pointer);
                    360:                    }
                    361:                        /* We could be in the situation of needing to exit.
                    362:                         * This could happen if the current field wrapped around
                    363:                         * the end of the screen.
                    364:                         */
                    365:                    if (j > pointer) {
                    366:                        /*
                    367:                         * pointer is guaranteed to be higher than Highest...
                    368:                         */
                    369:                        pointer = Highest+1;    /* We did the highest thing */
                    370:                        break;
                    371:                    }
                    372:                } else {
                    373:                    c = GetHost(pointer);
                    374:                        /* We always do the first character in a divergent
                    375:                         * field, since otherwise the start of a field in
                    376:                         * the Host structure may leave a highlighted blank
                    377:                         * on the screen, and the start of a field in the
                    378:                         * Terminal structure may leave a non-highlighted
                    379:                         * something in the middle of a highlighted field
                    380:                         * on the screen.
                    381:                         */
                    382:                    SetHighlightMode(pointer);
                    383:                    DoCharacterAt(c,pointer);
                    384:                }
                    385:            } else {
                    386:                SetHighlightMode(pointer);
                    387:                /*
                    388:                 * The following will terminate at least when we get back
                    389:                 * to the original 'pointer' location (since we force
                    390:                 * things to be equal).
                    391:                 */
                    392:                while (((c = GetHost(pointer)) != GetTerminal(pointer)) &&
                    393:                        !IsStartField(pointer) && !TermIsStartField(pointer)) {
                    394:                    DoCharacterAt(c, pointer);
                    395:                    pointer = ScreenInc(pointer);
                    396:                    if (!(--columnsleft)) {
                    397:                        DoARefresh();
                    398:                        EmptyTerminal();
                    399:                        if (HaveInput) {        /* if input came in, take it */
                    400:                            break;
                    401:                        }
                    402:                        move(ScreenLine(pointer), 0);
                    403:                        columnsleft = NumberColumns;
                    404:                    }
                    405:                }
                    406:            }
                    407:        }
                    408:     }
                    409:     DoARefresh();
                    410:     Lowest = pointer;
                    411:     if (Lowest > Highest) {            /* if we finished input... */
                    412:        Lowest = HighestScreen()+1;
                    413:        Highest = LowestScreen()-1;
                    414:        terminalCursorAddress = CorrectTerminalCursor();
                    415:        if (ERR == move(ScreenLine(terminalCursorAddress),
                    416:                        ScreenLineOffset(terminalCursorAddress))) {
                    417:            GoAway("move", terminalCursorAddress);
                    418:        }
                    419:        DoARefresh();
                    420:        if (needToRing) {
                    421:            StringToTerminal(bellSequence);
                    422:            needToRing = 0;
                    423:        }
                    424:     }
                    425:     EmptyTerminal();                   /* move data along */
                    426:     return;
                    427: }
                    428: 
                    429: #if    defined(NOT43)
                    430: static int
                    431: #else  /* defined(NOT43) */
                    432: static void
                    433: #endif /* defined(NOT43) */
                    434: FastScreen()
                    435: {
                    436: #if    defined(MSDOS)
                    437: #define        SaveCorner      0
                    438: #else  /* defined(MSDOS) */
                    439: #define        SaveCorner      1
                    440: #endif /* defined(MSDOS) */
                    441: 
                    442: #define        DoAttribute(a)      if (IsHighlightedAttr(a)) { \
                    443:                                standout(); \
                    444:                            } else { \
                    445:                                standend(); \
                    446:                            } \
                    447:                            if (IsNonDisplayAttr(a)) { \
                    448:                                a = 0;  /* zero == don't display */ \
                    449:                            } \
                    450:                            if (!FormattedScreen()) { \
                    451:                                a = 1;  /* one ==> do display on unformatted */\
                    452:                            }
                    453:     ScreenImage *p, *upper;
                    454:     int fieldattr;             /* spends most of its time == 0 or 1 */
                    455: 
                    456: /* OK.  We want to do this a quickly as possible.  So, we assume we
                    457:  * only need to go from Lowest to Highest.  However, if we find a
                    458:  * field in the middle, we do the whole screen.
                    459:  *
                    460:  * In particular, we separate out the two cases from the beginning.
                    461:  */
                    462:     if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
                    463:        register int columnsleft;
                    464: 
                    465:        move(ScreenLine(Lowest), ScreenLineOffset(Lowest));
                    466:        p = &Host[Lowest];
                    467: #if    !defined(MSDOS)
                    468:        if (Highest == HighestScreen()) {
                    469:            Highest = ScreenDec(Highest);
                    470:        }
                    471: #endif /* !defined(MSDOS) */
                    472:        upper = &Host[Highest];
                    473:        fieldattr = FieldAttributes(Lowest);
                    474:        DoAttribute(fieldattr); /* Set standout, non-display status */
                    475:        columnsleft = NumberColumns-ScreenLineOffset(p-Host);
                    476: 
                    477:        while (p <= upper) {
                    478:            if (IsStartFieldPointer(p)) {       /* New field? */
                    479:                Highest = HighestScreen();
                    480:                Lowest = LowestScreen();
                    481:                FastScreen();           /* Recurse */
                    482:                return;
                    483:            } else if (fieldattr) {     /* Should we display? */
                    484:                            /* Display translated data */
                    485:                addch(disp_asc[GetTerminalPointer(p)]);
                    486:            } else {
                    487:                addch(' ');                     /* Display a blank */
                    488:            }
                    489:                        /* If the physical screen is larger than what we
                    490:                         * are using, we need to make sure that each line
                    491:                         * starts at the beginning of the line.  Otherwise,
                    492:                         * we will just string all the lines together.
                    493:                         */
                    494:            p++;
                    495:            if (--columnsleft == 0) {
                    496:                int i = p-Host;
                    497: 
                    498:                move(ScreenLine(i), 0);
                    499:                columnsleft = NumberColumns;
                    500:            }
                    501:        }
                    502:     } else {           /* Going from Lowest to Highest */
                    503:        unsigned char tmpbuf[MAXNUMBERCOLUMNS+1];
                    504:        ScreenImage *End = &Host[ScreenSize]-1-SaveCorner;
                    505:        register unsigned char *tmp = tmpbuf, *tmpend = tmpbuf+NumberColumns;
                    506: 
                    507:        *tmpend = 0;            /* terminate from the beginning */
                    508:        move(0,0);
                    509:        p = Host;
                    510:        fieldattr = FieldAttributes(LowestScreen());
                    511:        DoAttribute(fieldattr); /* Set standout, non-display status */
                    512: 
                    513:        while (p <= End) {
                    514:            if (IsStartFieldPointer(p)) {       /* New field? */
                    515:                if (tmp != tmpbuf) {
                    516:                    *tmp++ = 0;                 /* close out */
                    517:                    addstr(tmpbuf);
                    518:                    tmp = tmpbuf;
                    519:                    tmpend = tmpbuf + NumberColumns - ScreenLineOffset(p-Host);
                    520:                }
                    521:                fieldattr = FieldAttributesPointer(p);  /* Get attributes */
                    522:                DoAttribute(fieldattr); /* Set standout, non-display */
                    523:                *tmp++ = ' ';
                    524:            } else {
                    525:                if (fieldattr) {        /* Should we display? */
                    526:                                /* Display translated data */
                    527:                    *tmp++ = disp_asc[GetTerminalPointer(p)];
                    528:                } else {
                    529:                    *tmp++ = ' ';
                    530:                }
                    531:            }
                    532:                        /* If the physical screen is larger than what we
                    533:                         * are using, we need to make sure that each line
                    534:                         * starts at the beginning of the line.  Otherwise,
                    535:                         * we will just string all the lines together.
                    536:                         */
                    537:            p++;
                    538:            if (tmp == tmpend) {
                    539:                int i = p-Host;         /* Be sure the "p++" happened first! */
                    540: 
                    541:                *tmp++ = 0;
                    542:                addstr(tmpbuf);
                    543:                tmp = tmpbuf;
                    544:                move(ScreenLine(i), 0);
                    545:                tmpend = tmpbuf + NumberColumns;
                    546:            }
                    547:        }
                    548:        if (tmp != tmpbuf) {
                    549:            *tmp++ = 0;
                    550:            addstr(tmpbuf);
                    551:            tmp = tmpbuf;
                    552:        }
                    553:     }
                    554:     Lowest = HighestScreen()+1;
                    555:     Highest = LowestScreen()-1;
                    556:     terminalCursorAddress = CorrectTerminalCursor();
                    557:     if (ERR == move(ScreenLine(terminalCursorAddress),
                    558:                    ScreenLineOffset(terminalCursorAddress))) {
                    559:        GoAway("move", terminalCursorAddress);
                    560:     }
                    561:     DoARefresh();
                    562:     if (needToRing) {
                    563:        StringToTerminal(bellSequence);
                    564:        needToRing = 0;
                    565:     }
                    566:     EmptyTerminal();                   /* move data along */
                    567:     return;
                    568: }
                    569: 
                    570: 
                    571: /* TryToSend - send data out to user's terminal */
                    572: 
                    573: #if    defined(NOT43)
                    574: int
                    575: #else  /* defined(NOT43) */
                    576: void
                    577: #endif /* defined(NOT43) */
                    578:        (*TryToSend)() = FastScreen;
                    579: 
                    580: void
                    581: ScreenOIA(oia)
                    582: OIA *oia;
                    583: {
                    584: }
                    585: 
                    586: 
                    587: /* InitTerminal - called to initialize the screen, etc. */
                    588: 
                    589: void
                    590: InitTerminal()
                    591: {
                    592: #if defined(unix)
                    593:     struct sgttyb ourttyb;
                    594:     static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
                    595:                2400, 4800, 9600 };
                    596: #endif
                    597:     
                    598:     InitMapping();             /* Go do mapping file (MAP3270) first */
                    599:     if (!screenInitd) {        /* not initialized */
                    600: #if    defined(unix)
                    601:        char KSEbuffer[2050];
                    602:        char *lotsofspace = KSEbuffer;
                    603:        extern int abort();
                    604:        extern char *tgetstr();
                    605: #endif /* defined(unix) */
                    606: 
                    607:        ClearArray(Terminal);
                    608:        terminalCursorAddress = SetBufferAddress(0,0);
                    609: #if defined(unix)
                    610:        signal(SIGHUP, abort);
                    611: #endif
                    612: 
                    613:        TryToSend = FastScreen;
                    614: #if defined(unix)
                    615:        ioctl(1, TIOCGETP, (char *) &ourttyb);
                    616:        if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) {
                    617:            max_changes_before_poll = 1920;
                    618:        } else {
                    619:            max_changes_before_poll = speeds[ourttyb.sg_ospeed]/10;
                    620:            if (max_changes_before_poll < 40) {
                    621:                max_changes_before_poll = 40;
                    622:            }
                    623:            TryToSend = SlowScreen;
                    624:            HaveInput = 1;              /* get signals going */
                    625:        }
                    626: #endif /* defined(unix) */
                    627:        setcommandmode();
                    628:        /*
                    629:         * By now, initscr() (in curses) has been called (from telnet.c),
                    630:         * and the screen has been initialized.
                    631:         */
                    632: #if defined(unix)
                    633:        nonl();
                    634:                        /* the problem is that curses catches SIGTSTP to
                    635:                         * be nice, but it messes us up.
                    636:                         */
                    637:        signal(SIGTSTP, SIG_DFL);
                    638:        if ((KS = tgetstr("ks", &lotsofspace)) != 0) {
                    639:            KS = strsave(KS);
                    640:            StringToTerminal(KS);
                    641:        }
                    642:        if ((KE = tgetstr("ke", &lotsofspace)) != 0) {
                    643:            KE = strsave(KE);
                    644:        }
                    645:        if (tgetstr("md", &lotsofspace) && tgetstr("me", &lotsofspace)) {
                    646:           SO = strsave(tgetstr("md", &lotsofspace));
                    647:           SE = strsave(tgetstr("me", &lotsofspace));
                    648:        }
                    649: #endif
                    650:        DoARefresh();
                    651:        setconnmode();
                    652:        if (VB && *VB) {
                    653:            bellSequence = VB;          /* use visual bell */
                    654:        }
                    655:        screenInitd = 1;
                    656:        screenStopped = 0;              /* Not stopped */
                    657:     }
                    658: }
                    659: 
                    660: 
                    661: /* StopScreen - called when we are going away... */
                    662: 
                    663: void
                    664: StopScreen(doNewLine)
                    665: int doNewLine;
                    666: {
                    667:     if (screenInitd && !screenStopped) {
                    668:        move(NumberLines-1, 1);
                    669:        standend();
                    670:        inHighlightMode = 0;
                    671:        DoARefresh();
                    672:        setcommandmode();
                    673:        endwin();
                    674:        setconnmode();
                    675: #if    defined(unix)
                    676:        if (KE) {
                    677:            StringToTerminal(KE);
                    678:        }
                    679: #endif /* defined(unix) */
                    680:        if (doNewLine) {
                    681:            StringToTerminal("\r\n");
                    682:        }
                    683:        EmptyTerminal();
                    684:        screenStopped = 1;              /* This is stopped */
                    685:     }
                    686: }
                    687: 
                    688: 
                    689: /* RefreshScreen - called to cause the screen to be refreshed */
                    690: 
                    691: void
                    692: RefreshScreen()
                    693: {
                    694:     clearok(curscr, TRUE);
                    695:     (*TryToSend)();
                    696: }
                    697: 
                    698: 
                    699: /* ConnectScreen - called to reconnect to the screen */
                    700: 
                    701: void
                    702: ConnectScreen()
                    703: {
                    704:     if (screenInitd) {
                    705: #if    defined(unix)
                    706:        if (KS) {
                    707:            StringToTerminal(KS);
                    708:        }
                    709: #endif /* defined(unix) */
                    710:        RefreshScreen();
                    711:        (*TryToSend)();
                    712:        screenStopped = 0;
                    713:     }
                    714: }
                    715: 
                    716: /* LocalClearScreen() - clear the whole ball of wax, cheaply */
                    717: 
                    718: void
                    719: LocalClearScreen()
                    720: {
                    721:     outputPurge();             /* flush all data to terminal */
                    722:     clear();                   /* clear in curses */
                    723:     ClearArray(Terminal);
                    724:     Clear3270();
                    725:     Lowest = HighestScreen()+1; /* everything in sync... */
                    726:     Highest = LowestScreen()+1;
                    727: }
                    728: 
                    729: 
                    730: void
                    731: BellOff()
                    732: {
                    733:     if (bellwinup) {
                    734:        delwin(bellwin);
                    735:        bellwin = 0;
                    736:        bellwinup = 0;
                    737:        touchwin(stdscr);
                    738:        DoARefresh();
                    739:     }
                    740: }
                    741: 
                    742: 
                    743: void
                    744: RingBell(s)
                    745: char *s;
                    746: {
                    747:     needToRing = 1;
                    748:     if (s) {
                    749:        int len = strlen(s);
                    750: 
                    751:        if (len > COLS-2) {
                    752:            len = COLS-2;
                    753:        }
                    754:        if ((bellwin = newwin(3, len+2, LINES/2, 0)) == NULL) {
                    755:            OurExitString(stderr, "Error from newwin in RingBell", 1);
                    756:        }
                    757:        werase(bellwin);
                    758:        wstandout(bellwin);
                    759:        box(bellwin, '|', '-');
                    760:        if (wmove(bellwin, 1, 1) == ERR) {
                    761:            OurExitString(stderr, "Error from wmove in RingBell", 1);
                    762:        }
                    763:        while (len--) {
                    764:            if (waddch(bellwin, *s++) == ERR) {
                    765:                OurExitString(stderr, "Error from waddch in RingBell", 1);
                    766:            }
                    767:        }
                    768:        wstandend(bellwin);
                    769:        if (wrefresh(bellwin) == ERR) {
                    770:            OurExitString(stderr, "Error from wrefresh in RingBell", 1);
                    771:        }
                    772:        bellwinup = 1;
                    773:     }
                    774: }
                    775: 
                    776: 
                    777: /* returns a 1 if no more output available (so, go ahead and block),
                    778:     or a 0 if there is more output available (so, just poll the other
                    779:     sources/destinations, don't block).
                    780:  */
                    781: 
                    782: int
                    783: DoTerminalOutput()
                    784: {
                    785:        /* called just before a select to conserve IO to terminal */
                    786:     if (!(screenInitd||screenStopped)) {
                    787:        return 1;               /* No output if not initialized */
                    788:     }
                    789:     if ((Lowest <= Highest) || needToRing ||
                    790:                        (terminalCursorAddress != CorrectTerminalCursor())) {
                    791:        (*TryToSend)();
                    792:     }
                    793:     if (Lowest > Highest) {
                    794:        return 1;               /* no more output now */
                    795:     } else {
                    796:        return 0;               /* more output for future */
                    797:     }
                    798: }
                    799: 
                    800: /*
                    801:  * The following are defined to handle transparent data.
                    802:  */
                    803: 
                    804: void
                    805: TransStop()
                    806: {
                    807: #if    defined(unix)
                    808:     if (tcflag == 0) {
                    809:        tcflag = -1;
                    810:        (void) signal(SIGCHLD, SIG_DFL);
                    811:     } else if (tcflag > 0) {
                    812:        setcommandmode();
                    813:        (void) close(tin);
                    814:        (void) close(tout);
                    815:        tin = savefd[0];
                    816:        tout = savefd[1];
                    817:        setconnmode();
                    818:        tcflag = -1;
                    819:        (void) signal(SIGCHLD, SIG_DFL);
                    820:     }
                    821: #endif /* defined(unix) */
                    822:     RefreshScreen();
                    823: }
                    824: 
                    825: void
                    826: TransOut(buffer, count, kind, control)
                    827: unsigned char  *buffer;
                    828: int            count;
                    829: int            kind;           /* 0 or 5 */
                    830: int            control;        /* To see if we are done */
                    831: {
                    832: #if    defined(unix)
                    833:     extern char *transcom;
                    834:     int inpipefd[2], outpipefd[2], savemode;
                    835:     void aborttc();
                    836: #endif /* defined(unix) */
                    837: 
                    838:     while (DoTerminalOutput() == 0) {
                    839: #if defined(unix)
                    840:        HaveInput = 0;
                    841: #endif /* defined(unix) */
                    842:     }
                    843: #if    defined(unix)
                    844:     if (transcom && tcflag == -1) {
                    845:        while (1) {                       /* go thru once */
                    846:             if (pipe(outpipefd) < 0) {
                    847:                break;
                    848:             }
                    849:             if (pipe(inpipefd) < 0) {
                    850:                break;
                    851:             }
                    852:             if ((tcflag = fork()) == 0) {
                    853:                (void) close(outpipefd[1]);
                    854:                (void) close(0);
                    855:                if (dup(outpipefd[0]) < 0) {
                    856:                   exit(1);
                    857:                }
                    858:                (void) close(outpipefd[0]);
                    859:                (void) close(inpipefd[0]);
                    860:                (void) close(1);
                    861:                if (dup(inpipefd[1]) < 0) {
                    862:                   exit(1);
                    863:                }
                    864:                (void) close(inpipefd[1]);
                    865:                if (execl("/bin/csh", "csh", "-c", transcom, (char *) 0)) {
                    866:                    exit(1);
                    867:                }
                    868:             }
                    869:             (void) close(inpipefd[1]);
                    870:             (void) close(outpipefd[0]);
                    871:             savefd[0] = tin;
                    872:             savefd[1] = tout;
                    873:             setcommandmode();
                    874:             tin = inpipefd[0];
                    875:             tout = outpipefd[1];
                    876:             (void) signal(SIGCHLD, aborttc);
                    877:             setconnmode();
                    878:             tcflag = 1;
                    879:             break;
                    880:        }
                    881:        if (tcflag < 1) {
                    882:          tcflag = 0;
                    883:        }
                    884:     }
                    885: #endif /* defined(unix) */
                    886:     (void) DataToTerminal(buffer, count);
                    887:     if (control && (kind == 0)) {              /* Send in AID byte */
                    888:        SendToIBM();
                    889:     } else {
                    890:        TransInput(1, kind);                    /* Go get some data */
                    891:     }
                    892: }
                    893: 
                    894: 
                    895: #if    defined(unix)
                    896: static void
                    897: aborttc()
                    898: {
                    899:        int savemode;
                    900: 
                    901:        setcommandmode();
                    902:        (void) close(tin);
                    903:        (void) close(tout);
                    904:        tin = savefd[0];
                    905:        tout = savefd[1];
                    906:        setconnmode();
                    907:        tcflag = 0;
                    908: }
                    909: #endif /* defined(unix) */

unix.superglobalmegacorp.com

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