Annotation of 43BSD/contrib/news/src/virtterm.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  Virtual terminal handler
        !             3:  *  Written by Kenneth Almquist, AGS Computers  (HO 4C601, X7105).
        !             4:  *  Modified by Stephen Hemminger, to use TERMCAP (without curses)
        !             5:  */
        !             6: 
        !             7: #ifdef SCCSID
        !             8: static char    *SccsId = "@(#)virtterm.c       1.10    1/17/86";
        !             9: #endif /* SCCSID */
        !            10: 
        !            11: /*LINTLIBRARY*/
        !            12: 
        !            13: #include <stdio.h>
        !            14: #include <ctype.h>
        !            15: #include <sys/types.h>
        !            16: #include <sys/ioctl.h>
        !            17: #include <signal.h>
        !            18: #ifdef USG
        !            19: #include <termio.h>
        !            20: #else /* !USG */
        !            21: #include <sgtty.h>
        !            22: #endif /* !USG */
        !            23: 
        !            24: /*
        !            25:  * These values for MAXPLEN and MAXLLEN are used to dimension arrays
        !            26:  * that hold strings of relative cursor motions.  The actual arrays that
        !            27:  * are used to hold screen images are malloc'd.
        !            28:  */
        !            29: #define MAXPLEN 90
        !            30: #define MAXLLEN 160
        !            31: 
        !            32: #define BOTLINE (ROWS - 1)
        !            33: #define DIRTY 01
        !            34: 
        !            35: /* terminal escape sequences from termcap */
        !            36: #define HO _tstr[0]            /* home */
        !            37: #define CL _tstr[1]            /* clear screen */
        !            38: #define CD _tstr[2]            /* clear to end of screen */
        !            39: #define CE _tstr[3]            /* clear to end of line */
        !            40: #define xUP _tstr[4]           /* up one line */
        !            41: #define DO _tstr[5]            /* down one line */
        !            42: #define US _tstr[6]            /* underline */
        !            43: #define UE _tstr[7]            /* underline end */
        !            44: #define BT _tstr[8]            /* backtab */
        !            45: #define xBC _tstr[9]           /* backspace */
        !            46: #define AL _tstr[10]           /* insert line */
        !            47: #define DL _tstr[11]           /* delete line */
        !            48: #define CM _tstr[12]           /* cursor move */
        !            49: #define CH _tstr[13]           /* cursor horizontal move */
        !            50: #define CV _tstr[14]           /* cursor vertical move */
        !            51: #define CS _tstr[15]           /* scrolling region */
        !            52: #define SF _tstr[16]           /* scroll forwards */
        !            53: #define SR _tstr[17]           /* scroll backwards */
        !            54: #define TI _tstr[18]           /* start cursor mode */
        !            55: #define TE _tstr[19]           /* end cursor mode */
        !            56: #define TA _tstr[20]           /* tab char (if not \t) */
        !            57: #define CR _tstr[21]           /* carriage return (if not \r) */
        !            58: #define xPC _tstr[22]          /* for reading pad character */
        !            59: char PC;                       /* pad character */
        !            60: char *BC, *UP;                 /* external variables for tgoto */
        !            61: 
        !            62: static char sname[] = "hoclcdceupdousuebtbcaldlcmchcvcssfsrtitetacrpc";
        !            63: char *_tstr[23];
        !            64: int     HOlen;                 /* length of HO string */
        !            65: 
        !            66: 
        !            67: /* terminal flags */
        !            68: #define BS _tflg[0]            /* can backspace */
        !            69: #define AM _tflg[1]            /* has auto margins */
        !            70: #define XN _tflg[2]            /* no newline after wrap */
        !            71: #define RET !_tflg[3]          /* has carriage return */
        !            72: #define NS _tflg[4]            /* has SF (scroll forward) */
        !            73: #define PT _tflg[5]            /* has tabs */
        !            74: #define XT _tflg[6]            /* tabs are destructive */
        !            75: int    GT = 1;                 /* tab stops on terminal are set */
        !            76: 
        !            77: static char bname[] = "bsamxnncnsptxt";
        !            78: char _tflg[7];
        !            79: 
        !            80: 
        !            81: extern char *tgoto(), *tgetstr();
        !            82: extern char *getenv(), *strcpy();
        !            83: 
        !            84: #define ULINE 0200
        !            85: 
        !            86: /* Constants accessable by user */
        !            87: int     hasscroll;             /* scrolling type, 0 == no scrolling */
        !            88: int     ROWS;                  /* number of lines on screen */
        !            89: int     COLS;                  /* width of screen */
        !            90: 
        !            91: struct line {
        !            92:        char    len;
        !            93:        char    flags;
        !            94:        char    *l;             /* pointer to actual line text, NO NULL @ end */
        !            95: };
        !            96: 
        !            97: int     _row, _col;
        !            98: int     _srow, _scol;
        !            99: struct line *_virt;            /* what we want the screen to look like */
        !           100: struct line *_actual;          /* What it actually looks like */
        !           101: int     _uline = 0;
        !           102: int     _junked = 1;
        !           103: int     _curjunked;
        !           104: int     _dir = 1;
        !           105: int    _shifttop, _shiftbot;
        !           106: int    _shift;
        !           107: int    _scratched;
        !           108: int     vputc();
        !           109: 
        !           110: /*
        !           111:  * Tell refresh to shift lines in region upwards count lines.  Count
        !           112:  * may be negative.  The virtual image is not shifted; this may change
        !           113:  * later.  The variable _scratched is set to supress all attempts to
        !           114:  * shift.
        !           115:  */
        !           116: 
        !           117: ushift(top, bot, count)
        !           118: {
        !           119:        if (_scratched)
        !           120:                return;
        !           121:        if (_shift != 0 && (_shifttop != top || _shiftbot != bot)) {
        !           122:                _scratched++;
        !           123:                return;
        !           124:        }
        !           125:        _shifttop = top;
        !           126:        _shiftbot = bot;
        !           127:        _shift += count;
        !           128: }
        !           129: 
        !           130: /*
        !           131:  * generate a beep on the terminal
        !           132:  */
        !           133: beep()
        !           134: {
        !           135:        vputc('\7');
        !           136: }
        !           137: 
        !           138: /*
        !           139:  * Move to one line below the bottom of the screen.
        !           140:  */
        !           141: botscreen()
        !           142: {
        !           143:        _amove(BOTLINE, 0);
        !           144:        vputc('\n');
        !           145:        vflush();
        !           146: }
        !           147: 
        !           148: move(row, col)
        !           149: {
        !           150:        if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
        !           151:                return;
        !           152:        _row = row;
        !           153:        _col = col;
        !           154: }
        !           155: 
        !           156: 
        !           157: 
        !           158: /*
        !           159:  * Output string at specified location.
        !           160:  */
        !           161: mvaddstr(row, col, str)
        !           162: char *str;
        !           163: {
        !           164:        move(row, col);
        !           165:        addstr(str);
        !           166: }
        !           167: 
        !           168: addstr(s)
        !           169: char   *s;
        !           170: {
        !           171:        register char  *p;
        !           172:        register struct line   *lp;
        !           173:        register int    col = _col;
        !           174: 
        !           175:        lp = &_virt[_row];
        !           176:        if (lp->len < col) {
        !           177:                p = &lp->l[lp->len];
        !           178:                while (lp->len < col) {
        !           179:                        *p++ = ' ';
        !           180:                        lp->len++;
        !           181:                }
        !           182:        }
        !           183:        for (p = s; *p != '\0'; p++) {
        !           184:                if (*p == '\n') {
        !           185:                        lp->len = col;
        !           186:                        lp->flags |= DIRTY;
        !           187:                        col = 0;
        !           188:                        if (++_row >= ROWS)
        !           189:                                _row = 0;
        !           190:                        lp = &_virt[_row];
        !           191:                }
        !           192:                else {
        !           193:                        lp->l[col] = *p;
        !           194:                        lp->flags |= DIRTY;
        !           195:                        if (++col >= COLS) {
        !           196:                                lp->len = COLS;
        !           197:                                col = 0;
        !           198:                                if (++_row >= ROWS)
        !           199:                                        _row = 0;
        !           200:                                lp = &_virt[_row];
        !           201:                        }
        !           202:                }
        !           203:        }
        !           204:        if (lp->len <= col)
        !           205:                lp->len = col;
        !           206:        _col = col;
        !           207: }
        !           208: 
        !           209: addch(c)
        !           210: {
        !           211:        register struct line   *lp;
        !           212:        register char  *p;
        !           213: 
        !           214:        lp = &_virt[_row];
        !           215:        if (lp->len < _col) {
        !           216:                p = &lp->l[lp->len];
        !           217:                while (lp->len < _col) {
        !           218:                        *p++ = ' ';
        !           219:                        lp->len++;
        !           220:                }
        !           221:        }
        !           222:        lp->l[_col] = c;
        !           223:        if (lp->len == _col)
        !           224:                lp->len++;
        !           225:        if (++_col >= COLS) {
        !           226:                _col = 0;
        !           227:                if (++_row >= ROWS)
        !           228:                        _row = 0;
        !           229:        }
        !           230:        lp->flags |= DIRTY;
        !           231: }
        !           232: 
        !           233: /*
        !           234:  * Clear an entire line.
        !           235:  */
        !           236: clrline(row)
        !           237: {
        !           238:        register struct line   *lp;
        !           239: 
        !           240:        lp = &_virt[row];
        !           241:        if (lp->len > 0) {
        !           242:                lp->len = 0;
        !           243:                lp->flags |= DIRTY;
        !           244:        }
        !           245: }
        !           246: 
        !           247: erase()
        !           248: {
        !           249:        register    i;
        !           250: 
        !           251:        for (i = 0; i < ROWS; i++) {
        !           252:                _virt[i].len = 0;
        !           253:                _virt[i].flags |= DIRTY;
        !           254:        }
        !           255: }
        !           256: 
        !           257: refresh()
        !           258: {
        !           259:        register i;
        !           260:        register char *p, *q;
        !           261:        register int j, len;
        !           262: 
        !           263:        if (checkin())
        !           264:                return;
        !           265:        i = 1;
        !           266:        if (_junked) {
        !           267:                _sclear();
        !           268:                _junked = 0;
        !           269:        } else if (! _scratched) {
        !           270:                if (_shift > 0) {
        !           271:                        _ushift(_shifttop, _shiftbot, _shift);
        !           272:                } else if (_shift < 0) {
        !           273:                        i = _dshift(_shifttop, _shiftbot, -_shift);
        !           274:                } else {
        !           275:                        i = _dir;
        !           276:                }
        !           277:        }
        !           278:        _dir = i;
        !           279:        _shift = 0;
        !           280:        if (checkin())
        !           281:                return;
        !           282:        _fixlines();
        !           283:        for (i = _dir > 0 ? 0 : BOTLINE; i >= 0 && i < ROWS; i += _dir) {
        !           284:                if ((_virt[i].flags & DIRTY) == 0)
        !           285:                        continue;
        !           286:                _ckclrlin(i);           /* decide whether to do a clear line */
        !           287:                                        /* probably should consider cd too  */
        !           288:                len = _virt[i].len;
        !           289:                if (_actual[i].len < len)
        !           290:                        len = _actual[i].len;
        !           291:                p = _virt[i].l;
        !           292:                q = _actual[i].l;
        !           293:                for (j = 0; j < len; j++) {
        !           294:                        if (*p != *q) {
        !           295:                                /* Inline test for speed */
        !           296:                                if (i != _srow || j != _scol || _curjunked)
        !           297:                                        _amove(i, j);
        !           298:                                _aputc(*p);
        !           299:                                *q = *p;
        !           300:                        }
        !           301:                        p++;
        !           302:                        q++;
        !           303:                }
        !           304:                len = _virt[i].len;
        !           305:                if (_actual[i].len > len) {
        !           306:                        _clrtoeol(i, len);
        !           307:                } else {
        !           308:                        for (; j < len; j++) {
        !           309:                                if (*p != ' ') {
        !           310:                                        /* Inline test for speed */
        !           311:                                        if (i != _srow || j != _scol || _curjunked)
        !           312:                                                _amove(i, j);
        !           313:                                        _aputc(*p);
        !           314:                                }
        !           315:                                *q++ = *p++;
        !           316:                        }
        !           317:                        _actual[i].len = len;
        !           318:                }
        !           319:                if (checkin())
        !           320:                        return;
        !           321:        }
        !           322:        _dir = 1;
        !           323:        _amove(_row, _col);
        !           324:        vflush();                       /* flush output buffer */
        !           325:        _scratched = 0;
        !           326: }
        !           327: 
        !           328: _dshift(top, bot, count)
        !           329: {
        !           330:        register    i;
        !           331: 
        !           332:        if (count >= bot - top || hasscroll < 4) {  /* must have CS or AL/DL */
        !           333:                _scratched++;
        !           334:                return 1;
        !           335:        }
        !           336:        for (i = bot - count; _actual[i].len == 0; i--)
        !           337:                if (i == top)
        !           338:                        return 1;
        !           339:        for (i = top; i <= bot; i++)
        !           340:                _virt[i].flags |= DIRTY;
        !           341:        for (i = bot; i >= top + count; i--) {
        !           342:                /* FIXME, this should be done by recirculating the pointers */
        !           343:                register j;
        !           344:                j =     _actual[i].len   = _actual[i - count].len;
        !           345:                        _actual[i].flags = _actual[i - count].flags;
        !           346:                strncpy(_actual[i].l,      _actual[i - count].l, j);
        !           347:        }
        !           348:        for (; i >= top; i--)
        !           349:                _actual[i].len = 0;
        !           350: 
        !           351:        if (hasscroll != 5) {           /* can we define scrolling region, and scroll back */
        !           352:                tputs(tgoto(CS, bot, top), 1, vputc);/* define scroll region */
        !           353:                _curjunked = 1;
        !           354:                _amove(top, 0);
        !           355:                for (i = count; --i >= 0;)
        !           356:                        tputs(SR, 1, vputc);/* scroll back */
        !           357:                tputs(tgoto(CS, BOTLINE, 0), 1, vputc);
        !           358:                _curjunked = 1;
        !           359:        } else {
        !           360:                _amove(bot - count + 1, 0);
        !           361:                if (CD && bot == BOTLINE)
        !           362:                        tputs(CD, 1, vputc);
        !           363:                else {
        !           364:                        for (i = count; --i >= 0;)
        !           365:                                tputs(DL, ROWS - _srow, vputc);
        !           366:                }
        !           367:                _amove(top, 0);
        !           368:                for (i = count; --i >= 0;)
        !           369:                        tputs(AL, ROWS - _srow, vputc);
        !           370:        }
        !           371:        return -1;
        !           372: }
        !           373: 
        !           374: 
        !           375: _ushift(top, bot, count)
        !           376: {
        !           377:        register    i;
        !           378: 
        !           379:        if (count >= bot - top || hasscroll == 0) {
        !           380:                _scratched++;
        !           381:                return;
        !           382:        }
        !           383:        for (i = top + count; _actual[i].len == 0; i++)
        !           384:                if (i == bot)
        !           385:                        return;
        !           386:        if (hasscroll == 1 || hasscroll == 3) {
        !           387:                /* we cheat and shift the entire screen */
        !           388:                /* be sure we are shifting more lines into than out of position */
        !           389:                if ((bot - top + 1) - count <= ROWS - (bot - top + 1))
        !           390:                        return;
        !           391:                top = 0, bot = BOTLINE;
        !           392:        }
        !           393:        for (i = top; i <= bot; i++)
        !           394:                _virt[i].flags |= DIRTY;
        !           395:        for (i = top; i <= bot - count; i++) {
        !           396:                /* FIXME, this should be done by recirculating the pointers */
        !           397:                register int j;
        !           398:                j =     _actual[i].len   = _actual[i + count].len;
        !           399:                        _actual[i].flags = _actual[i + count].flags;
        !           400:                strncpy(_actual[i].l,      _actual[i + count].l, j);
        !           401:        }
        !           402:        for (; i <= bot; i++)
        !           403:        for (; i <= bot; i++)
        !           404:                _actual[i].len = 0;
        !           405: 
        !           406:        if (hasscroll != 5) {
        !           407:                if (top != 0 || bot != BOTLINE) {
        !           408:                        tputs(tgoto(CS, bot, top), 0, vputc);
        !           409:                        _curjunked = 1;
        !           410:                }
        !           411:                _amove(bot, 0); /* move to bottom */
        !           412:                for (i = 0; i < count; i++) {
        !           413:                        if (SF)         /* scroll forward */
        !           414:                                tputs(SF, 1, vputc);
        !           415:                        else
        !           416:                                vputc('\n');
        !           417:                }
        !           418:                if (top != 0 || bot != BOTLINE) {
        !           419:                        tputs(tgoto(CS, BOTLINE, 0), 0, vputc);
        !           420:                        _curjunked = 1;
        !           421:                }
        !           422:        } else {
        !           423:                _amove(top, 0);
        !           424:                for (i = count; --i >= 0;)
        !           425:                        tputs(DL, ROWS - _srow, vputc);
        !           426:                if (bot < BOTLINE) {
        !           427:                        _amove(bot - count + 1, 0);
        !           428:                        for (i = count; --i >= 0;)
        !           429:                                tputs(AL, ROWS - _srow, vputc);
        !           430:                }
        !           431:        }
        !           432: }
        !           433: 
        !           434: _sclear()
        !           435: {
        !           436:        register struct line   *lp;
        !           437: 
        !           438:        tputs(CL, 0, vputc);
        !           439:        _srow = _scol = 0;
        !           440:        for (lp = _actual; lp < &_actual[ROWS]; lp++) {
        !           441:                lp->len = 0;
        !           442:        }
        !           443:        for (lp = _virt; lp < &_virt[ROWS]; lp++) {
        !           444:                if (lp->len != 0)
        !           445:                        lp->flags |= DIRTY;
        !           446:        }
        !           447: }
        !           448: 
        !           449: _clrtoeol(row, col)
        !           450: {
        !           451:        register struct line *lp = &_actual[row];
        !           452:        register i;
        !           453: 
        !           454:        if (CE && lp->len > col + 1) {
        !           455:                _amove(row, col);
        !           456:                tputs(CE, 1, vputc);
        !           457:        } else {
        !           458:                for (i = col ; i < lp->len ; i++) {
        !           459:                        if (lp->l[i] != ' ') {
        !           460:                                _amove(row, i);
        !           461:                                _aputc(' ');
        !           462:                        }
        !           463:                }
        !           464:        }
        !           465:        lp->len = col;
        !           466: }
        !           467: 
        !           468: _fixlines()
        !           469: {
        !           470:        register struct line   *lp;
        !           471:        register char  *p;
        !           472:        register int    i;
        !           473: 
        !           474:        for (i = 0; i < ROWS; i++) {
        !           475:                lp = &_virt[i];
        !           476:                if (lp->flags & DIRTY) {
        !           477:                        for (p = &lp->l[lp->len]; --p >= lp->l && *p == ' ';)
        !           478:                                ;
        !           479:                        lp->len = (int) (p - lp->l) + 1;
        !           480:                        if (lp->len == _actual[i].len && strncmp(lp->l, _actual[i].l, lp->len) == 0)
        !           481:                                lp->flags &= ~DIRTY;
        !           482:                }
        !           483:        }
        !           484: }
        !           485: 
        !           486: 
        !           487: /*
        !           488:  * Consider clearing the line before overwriting it.
        !           489:  * We always clear a line if it has underlined characters in it
        !           490:  * because these can cause problems.  Otherwise decide whether
        !           491:  * that will decrease the number of characters to change.  This
        !           492:  * routine could probably be simplified with no great loss.
        !           493:  */
        !           494: 
        !           495: _ckclrlin(i)
        !           496: {
        !           497:        int     eval;
        !           498:        int     len;
        !           499:        int     first;
        !           500:        register struct line   *vp, *ap;
        !           501:        register int    j;
        !           502: 
        !           503:        if (!CE)
        !           504:                return;
        !           505:        ap = &_actual[i];
        !           506:        vp = &_virt[i];
        !           507:        len = ap->len;
        !           508:        eval = -strlen(CE);
        !           509:        if (len > vp->len) {
        !           510:                len = vp->len;
        !           511:                eval = 0;
        !           512:        }
        !           513:        for (j = 0; j < len && vp->l[j] == ap->l[j]; j++)
        !           514:                ;
        !           515:        if (j == len)
        !           516:                return;
        !           517:        first = j;
        !           518:        while (j < len) {
        !           519:                if (vp->l[j] == ' ') {
        !           520:                        if (ap->l[j] != ' ') {
        !           521:                                while (++j < len && vp->l[j] == ' ' && ap->l[j] != ' ') {
        !           522:                                        eval++;
        !           523:                                }
        !           524:                                if (j == len)
        !           525:                                        eval++;
        !           526:                                continue;
        !           527:                        }
        !           528:                }
        !           529:                else {
        !           530:                        if (vp->l[j] == ap->l[j]) {
        !           531:                                while (++j < len && vp->l[j] == ap->l[j]) {
        !           532:                                        eval--;
        !           533:                                }
        !           534:                                continue;
        !           535:                        }
        !           536:                }
        !           537:                j++;
        !           538:        }
        !           539:        if (US) {
        !           540:                for (j = 0 ; j < ap->len ; j++) {
        !           541:                        if (ap->l[j] & ULINE) {
        !           542:                                eval = 999;
        !           543:                                if (first > j)
        !           544:                                        first = j;
        !           545:                                break;
        !           546:                        }
        !           547:                }
        !           548:        }
        !           549:        for (j = first; --j >= 0;)
        !           550:                if (vp->l[j] != ' ')
        !           551:                        break;
        !           552:        if (j < 0)
        !           553:                first = 0;
        !           554:        if (eval > 0) {
        !           555:                _amove(i, first);
        !           556:                tputs(CE, 0, vputc);
        !           557:                _actual[i].len = first;
        !           558:        }
        !           559: }
        !           560: 
        !           561: 
        !           562: 
        !           563: /*
        !           564:  * Move routine
        !           565:  *     first compute direct cursor address string and cost
        !           566:  *     then relative motion string and cost,
        !           567:  *     then home then relative and cost
        !           568:  *     choose smallest and do it.
        !           569:  *
        !           570:  *     The plod stuff is to build the strings (with padding) then decide
        !           571:  */
        !           572: static char *plodstr;          /* current location in relmove string */
        !           573: 
        !           574: plodput(c)
        !           575: {
        !           576:        *plodstr++ = c;
        !           577: }
        !           578: 
        !           579: /* FIXME: speedup 1-char horiz moves:  print the char that's there. */
        !           580: /* FIXME: avoid funniness if cm works. */
        !           581: /* FIXME: Avoid setul(0) if cursor motion OK in standout (XM?) */
        !           582: _amove(row, col)
        !           583: {
        !           584:        char direct[20];
        !           585:        char rel[MAXPLEN*10 + MAXLLEN*10];    /* longest move is full screen */
        !           586:        char ho[MAXPLEN*10 + MAXLLEN*10];
        !           587:        int cost, newcost;
        !           588:        register char *movstr;
        !           589: 
        !           590:        if (row == _srow && col == _scol && _curjunked == 0)
        !           591:                return;
        !           592:        if (_uline)
        !           593:                _setul(0);      /* Inline test for speed */
        !           594: 
        !           595:        cost = 999;
        !           596:        if (CM) {
        !           597:                plodstr = direct;
        !           598:                tputs(tgoto(CM, col, row), 0, plodput);
        !           599:                cost = plodstr - direct;
        !           600:                movstr = direct;
        !           601:        }
        !           602:        if (_curjunked == 0) {
        !           603:                plodstr = rel;
        !           604:                if (_vmove(_srow, row) >= 0
        !           605:                 && (plodstr - rel) < cost              /* after vmove */
        !           606:                 && _hmove(_scol, col, row) >= 0
        !           607:                 && (newcost = plodstr - rel) < cost) { /* after both */
        !           608:                        cost = newcost;
        !           609:                        movstr = rel;
        !           610:                }
        !           611:        }
        !           612:        if (cost > HOlen) {     /* is it worth calculating */
        !           613:                plodstr = ho;
        !           614:                tputs(HO, 0, plodput);
        !           615:                if (_vmove(0, row) >= 0
        !           616:                 && (plodstr - ho) < cost               /* after ho, vmove */
        !           617:                 && _hmove(0, col, row) >= 0
        !           618:                 && (newcost = plodstr - ho) < cost) {  /* after all three */
        !           619:                        cost = newcost;
        !           620:                        movstr = ho;
        !           621:                }
        !           622:        }
        !           623: 
        !           624:        if (cost < 999)
        !           625:                while (--cost >= 0)
        !           626:                        vputc(*movstr++);
        !           627: 
        !           628:        _srow = row;
        !           629:        _scol = col;
        !           630:        _curjunked = 0;
        !           631: }
        !           632: 
        !           633: _vmove(orow, nrow)
        !           634: {
        !           635:        char direct[128];
        !           636:        char *saveplod = plodstr;
        !           637: 
        !           638:        if (CV) {
        !           639:                plodstr = direct;
        !           640:                tputs(tgoto(CV, nrow, nrow), 0, plodput);
        !           641:                *plodstr = '\0';
        !           642:                plodstr = saveplod;
        !           643:        }
        !           644:        if (orow > nrow) {              /* cursor up */
        !           645:                if (! UP)
        !           646:                        return -1;
        !           647:                while (orow > nrow) {
        !           648:                        tputs(UP, 1, plodput);
        !           649:                        orow--;
        !           650:                }
        !           651:        }
        !           652:        while (orow < nrow) {           /* cursor down */
        !           653:                if (DO)
        !           654:                        tputs(DO, 1, plodput);
        !           655:                else
        !           656:                        *plodstr++ = '\n';
        !           657:                orow++;
        !           658:        }
        !           659:        if (CV && plodstr - saveplod >= strlen(direct)) {
        !           660:                register char *p;
        !           661:                plodstr = saveplod;
        !           662:                for (p = direct ; *plodstr = *p++ ; plodstr++)
        !           663:                        ;
        !           664:        }
        !           665:        return 0;
        !           666: }
        !           667: 
        !           668: _hmove(ocol, ncol, row)
        !           669: {
        !           670:        char direct[128];
        !           671:        char ret[MAXLLEN*10];
        !           672:        char *saveplod = plodstr;
        !           673:        char *movstr;
        !           674:        int cost, newcost;
        !           675: 
        !           676:        cost = 999;
        !           677:        if (CH) {
        !           678:                plodstr = direct;
        !           679:                tputs(tgoto(CH, ncol, ncol), 0, plodput);
        !           680:                cost = plodstr - direct;
        !           681:                movstr = direct;
        !           682:                plodstr = saveplod;
        !           683:        }
        !           684:        if (RET && ocol > ncol) {       /* consider doing carriage return */
        !           685:                plodstr = ret;
        !           686:                if (CR)
        !           687:                        tputs(CR, 1, plodput);
        !           688:                else
        !           689:                        *plodstr++ = '\r';
        !           690:                if (_relhmove(0, ncol, row) >= 0
        !           691:                 && (newcost = plodstr - ret) < cost) {
        !           692:                        cost = newcost;
        !           693:                        movstr = ret;
        !           694:                }
        !           695:                plodstr = saveplod;
        !           696:        }
        !           697:        if (_relhmove(ocol, ncol, row) < 0) {
        !           698:                if (cost == 999)
        !           699:                        return -1;
        !           700:                goto copy;
        !           701:        }
        !           702:        if (plodstr - saveplod > cost) {
        !           703: copy:          plodstr = saveplod;
        !           704:                while (--cost >= 0)
        !           705:                        *plodstr++ = *movstr++;
        !           706:        }
        !           707:        return 0;
        !           708: }
        !           709: 
        !           710: _relhmove(ocol, ncol, row)
        !           711: {
        !           712:        int tab;
        !           713: 
        !           714:        if (ocol < ncol && PT && GT) {  /* tab (nondestructive) */
        !           715:                while ((tab = (ocol + 8) & ~07) <= ncol) {
        !           716:                        if (TA)
        !           717:                                tputs(TA, 1, plodput);
        !           718:                        else
        !           719:                                *plodstr++ = '\t';
        !           720:                        ocol = tab;
        !           721:                }
        !           722:                if (tab < COLS && tab - ncol < ncol - ocol) {
        !           723:                        if (TA)
        !           724:                                tputs(TA, 1, plodput);
        !           725:                        else
        !           726:                                *plodstr++ = '\t';
        !           727:                        ocol = tab;
        !           728:                }
        !           729:        } else if (BT && GT && ocol > ncol) {   /* backwards tab */
        !           730:                while ((tab = (ocol - 1) &~ 07) >= ncol) {
        !           731:                        if (BS && tab == ocol - 1) {
        !           732:                                if (BC)
        !           733:                                        tputs(BC, 1, plodput);
        !           734:                                else
        !           735:                                        *plodstr++ = '\b';
        !           736:                        } else
        !           737:                                tputs(BT, 1, plodput);
        !           738:                        ocol = tab;
        !           739:                }
        !           740:                if (ncol - tab + 1 < ocol - ncol) {
        !           741:                        tputs(BT, 1, plodput);
        !           742:                        ocol = tab;
        !           743:                }
        !           744:        }
        !           745:        if (ocol > ncol) {                      /* cursor left */
        !           746:                if (! BS)
        !           747:                        return -1;
        !           748:                while (ocol > ncol) {
        !           749:                        if (BC != NULL)
        !           750:                                tputs(BC, 1, plodput);
        !           751:                        else
        !           752:                                *plodstr++ = '\b';
        !           753:                        ocol--;
        !           754:                }
        !           755:        }
        !           756:        if (ocol < ncol) {                      /* cursor right */
        !           757:                register struct line *lp = &_actual[row];
        !           758:                /*
        !           759:                 * This code doesn't move over underlined characters properly,
        !           760:                 * but in practice this doesn't seem to matter.
        !           761:                 */
        !           762:                while (ocol < ncol) {
        !           763:                        if (ocol < lp->len)
        !           764:                                *plodstr++ = lp->l[ocol];
        !           765:                        else
        !           766:                                *plodstr++ = ' ';
        !           767:                        ocol++;
        !           768:                }
        !           769:        }
        !           770:        return 0;
        !           771: }
        !           772: 
        !           773: _aputc(c)
        !           774: {
        !           775:        if (_uline != (c & ULINE))      /* Inline for speed */
        !           776:                _setul(c & ULINE);
        !           777:        if (++_scol >= COLS) {
        !           778:                if (_srow == ROWS - 1) {
        !           779:                        /* Don't ever paint last char of last line */
        !           780:                        _scol--;
        !           781:                        return;
        !           782:                }
        !           783:                _curjunked++;           /* Don't assume AM is right */
        !           784:        }
        !           785:        vputc(c & ~ULINE);
        !           786: }
        !           787: 
        !           788: 
        !           789: _setul(on)
        !           790: {
        !           791:        if (on) {
        !           792:                if (_uline == 0 && US != NULL) {
        !           793:                        tputs(US, 1, vputc);
        !           794:                        _uline = ULINE;
        !           795:                }
        !           796:        }
        !           797:        else {
        !           798:                if (_uline != 0 && UE != NULL) {
        !           799:                        tputs(UE, 1, vputc);
        !           800:                        _uline = 0;
        !           801:                }
        !           802:        }
        !           803: }
        !           804: 
        !           805: /*
        !           806:  * Initialize termcap strings for later use.
        !           807:  */
        !           808: initterm()
        !           809: {
        !           810:        static char tcbuf[1024];        /* termcap buffer */
        !           811:        register char  *cp;
        !           812: #ifdef USG
        !           813:        struct termio tio;
        !           814: #else /* !USG */
        !           815:        struct sgttyb ttyb;
        !           816: #endif /* !USG */
        !           817: 
        !           818:        if ((cp = getenv("TERM")) == NULL)
        !           819:                xerror("TERM not set in environment");
        !           820: 
        !           821:        switch (tgetent(tcbuf, cp)) {
        !           822:                case 0:
        !           823:                        xerror("Terminal not found in TERMCAP");
        !           824:                case -1:
        !           825:                        xerror("Can't open /etc/termcap");
        !           826:                case 1:
        !           827:                        break;
        !           828:        }
        !           829: #ifdef TIOCGWINSZ
        !           830:        {
        !           831:                struct winsize ws;
        !           832:                int winch();
        !           833: 
        !           834:                COLS = ROWS = -1;
        !           835:                if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
        !           836:                        ROWS = ws.ws_row;
        !           837:                        COLS = ws.ws_col;
        !           838:                }
        !           839:                if(ROWS <= 0)
        !           840:                        ROWS = tgetnum("li");
        !           841:                if(COLS <= 0)
        !           842:                        COLS = tgetnum("co");
        !           843:                if ((ROWS <= 0) || (COLS <= 0))
        !           844:                        xerror("Can't get screen size");
        !           845: 
        !           846:                signal(SIGWINCH, winch); /* allow for changing window size */
        !           847:        }
        !           848: #else /* !TIOCGWINSZ */
        !           849:        if ((ROWS = tgetnum("li")) == -1
        !           850:                || (COLS = tgetnum("co")) == -1)
        !           851:                xerror("Can't get screen size");
        !           852: #endif /* !TIOCGWINSZ */
        !           853:        _zap();
        !           854: 
        !           855:        if (CL == NULL)
        !           856:                xerror ("No clear screen defined");
        !           857: 
        !           858:        if (HO == NULL && CM == NULL)
        !           859:                xerror("No home or cursor addressing");
        !           860:        if (HO)
        !           861:                HOlen = strlen(HO);
        !           862:        else
        !           863:                HOlen = 999;
        !           864: 
        !           865:        PC = xPC ? xPC[0] : 0;
        !           866:        BC = xBC;
        !           867:        UP = xUP;
        !           868: 
        !           869:        if (tgetnum("ug") > 0)
        !           870:                US = UE = NULL;
        !           871: 
        !           872:        if (XT)                         /* Destructive tab code not included */
        !           873:                PT = 0;                 /* to keep things simple */
        !           874: 
        !           875: #ifdef USG
        !           876:        if (ioctl(0, TCGETA, &tio) == 0)
        !           877:                GT = tio.c_oflag&TAB3;
        !           878: #else /* !USG */
        !           879:        if (ioctl(0, TIOCGETP, &ttyb) == 0)
        !           880:                GT = ttyb.sg_flags&XTABS;
        !           881: #endif /* !USG */
        !           882: 
        !           883:        {
        !           884:                char *thelines;
        !           885:                int i;
        !           886:                char *malloc();
        !           887: 
        !           888:                thelines = malloc(2 * ROWS * COLS);
        !           889:                _virt = (struct line *)malloc(2 * ROWS * sizeof (struct line));
        !           890:                _actual = _virt + ROWS;
        !           891:                for (i = 0; i < ROWS; i++) {
        !           892:                        _virt[i].len = 0;
        !           893:                        _virt[i].flags = 0;
        !           894:                        _actual[i].len = 0;
        !           895:                        _actual[i].flags = 0;
        !           896:                        _virt[i].l = thelines;
        !           897:                        thelines += COLS;
        !           898:                        _actual[i].l = thelines;
        !           899:                        thelines += COLS;
        !           900:                }
        !           901:        }
        !           902: 
        !           903:        /* Select article scrolling algorithm.  We prefer scrolling region
        !           904:           over insert/delete line because it's faster on the HP */
        !           905:        hasscroll = 0;
        !           906:        if (!NS) {
        !           907:                hasscroll = 1;
        !           908:                if (SR)
        !           909:                        hasscroll = 3;
        !           910:                if (CS)
        !           911:                        hasscroll++;
        !           912:        }
        !           913:        if (AL && DL && hasscroll != 4)
        !           914:                hasscroll = 5;
        !           915: }
        !           916: 
        !           917: rawterm()
        !           918: {
        !           919:        if (TI != NULL)
        !           920:                tputs(TI, 0, vputc);
        !           921: }
        !           922: 
        !           923: cookedterm()
        !           924: {
        !           925:        if (TE != NULL) {
        !           926:                tputs(TE, 0, vputc);
        !           927:                vflush();
        !           928:        }
        !           929: }
        !           930: 
        !           931: /* get strings from termcap */
        !           932: _zap()
        !           933: {
        !           934:        static char tstrbuf[1024];
        !           935:        static char *tp;
        !           936:        register char  *namp, **sp, *bp;
        !           937: 
        !           938:        tp = tstrbuf;
        !           939:        sp = _tstr;
        !           940:        for (namp = sname; *namp; namp += 2) {
        !           941:                *sp++ = tgetstr(namp, &tp);
        !           942:        }
        !           943:        bp = _tflg;
        !           944:        for (namp = bname; *namp; namp += 2) {
        !           945:                *bp++ = tgetflag(namp, &tp);
        !           946:        }
        !           947: }
        !           948: #ifdef TIOCGWINSZ
        !           949: /*
        !           950:  * window changed size -- update ROWS and COLS
        !           951:  * and then redraw screen
        !           952:  */
        !           953: winch()
        !           954: {
        !           955:        struct winsize ws;
        !           956:        int cols, rows;
        !           957: 
        !           958:        cols = rows = -1;
        !           959:        if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
        !           960:                rows = ws.ws_row;
        !           961:                cols = ws.ws_col;
        !           962:        }
        !           963:        if (rows == ROWS && cols == COLS) { /* just redraw it if no change */
        !           964:                _junked = 1;    /* redraw */
        !           965:                updscr();
        !           966:                return;
        !           967:        }
        !           968: 
        !           969:        if(rows > 0)
        !           970:                ROWS = rows;
        !           971:        if(cols > 0)
        !           972:                COLS = cols;
        !           973: 
        !           974:        if (ROWS > MAXPLEN)
        !           975:                ROWS = MAXPLEN;
        !           976:        if (COLS > MAXLLEN) {
        !           977:                COLS = MAXLLEN;
        !           978:                AM = XN = 1;
        !           979:        }
        !           980: 
        !           981:        winch_upd();
        !           982: }
        !           983: #endif TIOCGWINSZ

unix.superglobalmegacorp.com

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