Annotation of 43BSD/contrib/news/src/virtterm.c, revision 1.1.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.