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