Annotation of 43BSD/contrib/jove/disp.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
                      3:  * provided to you without charge for use only on a licensed Unix        *
                      4:  * system.  You may copy JOVE provided that this notice is included with *
                      5:  * the copy.  You may not sell copies of this program or versions        *
                      6:  * modified for use on microcomputer systems, unless the copies are      *
                      7:  * included with a Unix system distribution and the source is provided.  *
                      8:  *************************************************************************/
                      9: 
                     10: #include "jove.h"
                     11: #include "ctype.h"
                     12: #include "termcap.h"
                     13: 
                     14: #include <varargs.h>
                     15: #include <signal.h>
                     16: #include <sys/stat.h>
                     17: 
                     18: /* Kludge windows gets called by the routines that delete lines from the
                     19:    buffer.  If the w->w_line or w->w_top are deleted and this procedure
                     20:    is not called, the redisplay routine will barf. */
                     21: 
                     22: ChkWindows(line1, line2)
                     23: Line   *line1;
                     24: register Line  *line2;
                     25: {
                     26:        register Window *w = fwind;
                     27:        register Line   *lp;
                     28: 
                     29:        do {
                     30:                for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) {
                     31:                        if (lp == w->w_top)
                     32:                                w->w_flags |= TOPGONE;
                     33:                        if (lp == w->w_line)
                     34:                                w->w_flags |= CURGONE;
                     35:                }
                     36:                w = w->w_next;
                     37:        } while (w != fwind);
                     38: }
                     39: 
                     40: extern int     RingBell;
                     41: 
                     42: redisplay()
                     43: {
                     44:        register Window *w = fwind;
                     45:        int     lineno,
                     46:                done_ID = 0,
                     47:                i;
                     48:        register struct scrimage        *des_p,
                     49:                                        *phys_p;
                     50: 
                     51:        curwind->w_line = curwind->w_bufp->b_dot;
                     52:        curwind->w_char = curwind->w_bufp->b_char;
                     53: 
                     54:        if (InputPending = charp())
                     55:                return;
                     56: 
                     57: #ifdef JOB_CONTROL
                     58:        if (UpdFreq)
                     59:                sighold(SIGALRM);
                     60: #endif
                     61:        if (RingBell) {
                     62:                dobell(1);
                     63:                RingBell = 0;
                     64:        }
                     65:        if (UpdMesg)
                     66:                DrawMesg(YES);
                     67: 
                     68:        for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
                     69:                UpdWindow(w, lineno);
                     70:                lineno += w->w_height;
                     71:        }
                     72: 
                     73:        des_p = DesiredScreen;
                     74:        phys_p = PhysScreen;
                     75:        for (i = 0; i < ILI; i++, des_p++, phys_p++) {
                     76:                if (!done_ID && (des_p->s_id != phys_p->s_id)) {
                     77:                        DoIDline(i);
                     78:                        done_ID++;
                     79:                }
                     80:                if ((des_p->s_flags & (DIRTY | L_MOD)) ||
                     81:                    (des_p->s_id != phys_p->s_id) ||
                     82:                    (des_p->s_vln != phys_p->s_vln) ||
                     83:                    (des_p->s_offset != phys_p->s_offset))
                     84:                        UpdLine(i);
                     85:                if (InputPending)
                     86:                        goto ret;
                     87:        }
                     88: 
                     89:        UpdModLine = 0;
                     90: 
                     91:        if (Asking) {
                     92:                Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking)));
                     93:                        /* Nice kludge */
                     94:                flusho();
                     95:        } else
                     96:                GotoDot();
                     97: ret:
                     98: #ifdef JOB_CONTROL
                     99:        if (UpdFreq)
                    100:                sigrelse(SIGALRM);
                    101: #else
                    102:        ;       /* yuck */
                    103: #endif
                    104: 
                    105: }
                    106: 
                    107: dobell(n)
                    108: {
                    109:        while (--n >= 0) {
                    110:                if (VisBell && VB)
                    111:                        putstr(VB);
                    112:                else
                    113:                        putpad("20\007", 1);
                    114:        }
                    115:        flusho();
                    116: }
                    117: 
                    118: /* find_pos() returns the position on the line, that c_char represents
                    119:    in line. */
                    120: 
                    121: find_pos(line, c_char)
                    122: Line   *line;
                    123: {
                    124:        return calc_pos(lcontents(line), c_char);
                    125: }
                    126: 
                    127: calc_pos(lp, c_char)
                    128: register char  *lp;
                    129: register int   c_char;
                    130: {
                    131:        register int    pos = 0;
                    132:        register int    c;
                    133: 
                    134:        while ((--c_char >= 0) && ((c = *lp++) & 0177) != 0) {
                    135:                if (c == '\t')
                    136:                        pos += (tabstop - (pos % tabstop));
                    137:                else if (isctrl(c))
                    138:                        pos += 2;
                    139:                else
                    140:                        pos++;
                    141:        }
                    142:        return pos;
                    143: }
                    144: 
                    145: int    UpdModLine = 0,
                    146:        UpdMesg = 0,
                    147:        CanScroll = 0;
                    148: 
                    149: DoIDline(start)
                    150: {
                    151:        register struct scrimage        *des_p = &DesiredScreen[start];
                    152:        struct scrimage *phys_p = &PhysScreen[start];
                    153:        register int    i,
                    154:                        j;
                    155: 
                    156:        /* Some changes have been made.  Try for insert or delete lines.
                    157:           If either case has happened, Addlines and/or DelLines will do
                    158:           necessary scrolling, also CONVERTING PhysScreen to account for the
                    159:           physical changes.  The comparison continues from where the
                    160:           insertion/deletion takes place; this doesn't happen very often,
                    161:           usually it happens with more than one window with the same
                    162:           buffer. */
                    163: 
                    164:        if (!CanScroll)
                    165:                return;         /* We should never have been called! */
                    166: 
                    167:        for (i = start; i < ILI; i++, des_p++, phys_p++)
                    168:                if (des_p->s_id != phys_p->s_id)
                    169:                        break;
                    170: 
                    171:        for (; i < ILI; i++) {
                    172:                for (j = i + 1; j < ILI; j++) {
                    173:                        des_p = &DesiredScreen[j];
                    174:                        phys_p = &PhysScreen[j];
                    175:                        if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
                    176:                                break;
                    177:                        if (des_p->s_id == PhysScreen[i].s_id) {
                    178:                                if (des_p->s_id == 0)
                    179:                                        continue;
                    180:                                if (AddLines(i, j - i)) {
                    181:                                        DoIDline(j);
                    182:                                        return;
                    183:                                }
                    184:                                break;
                    185:                        }
                    186:                        if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
                    187:                                if (des_p->s_id == 0)
                    188:                                        continue;
                    189:                                if (DelLines(i, j - i)) {
                    190:                                        DoIDline(i);
                    191:                                        return;
                    192:                                }
                    193:                                break;
                    194:                        }
                    195:                }
                    196:        }
                    197: }
                    198: 
                    199: /* Make DesiredScreen reflect what the screen should look like when we are done
                    200:    with the redisplay.  This deals with horizontal scrolling.  Also makes
                    201:    sure the current line of the Window is in the window. */
                    202: 
                    203: UpdWindow(w, start)
                    204: register Window        *w;
                    205: {
                    206:        Line    *lp;
                    207:        int     i,
                    208:                DotIsHere = 0,
                    209:                upper,          /* Top of window */
                    210:                lower,          /* Bottom of window */
                    211:                ntries = 0;     /* # of tries at updating window. */
                    212:        register struct scrimage        *des_p,
                    213:                                        *phys_p;
                    214:        Buffer  *bp = w->w_bufp;
                    215: 
                    216: retry:
                    217:        if (w->w_flags & CURGONE) {
                    218:                w->w_line = bp->b_dot;
                    219:                w->w_char = bp->b_char;
                    220:        }
                    221:        if (w->w_flags & TOPGONE)
                    222:                CentWind(w);    /* Reset topline of screen */
                    223:        w->w_flags = 0;
                    224:        for (i = w->w_height, lp = w->w_top; --i > 0 && lp != 0; lp = lp->l_next)
                    225:                if (lp == w->w_line)
                    226:                        break;
                    227:        if (i == 0 || lp == 0) {        /* Current line not in window */
                    228:                ntries++;
                    229:                if (ntries == 1) {
                    230:                        CalcWind(w);
                    231:                        goto retry;
                    232:                } else if (ntries == 2) {
                    233:                        w->w_top = w->w_line = w->w_bufp->b_first;
                    234:                        f_mess("ERROR in redisplay: I got hopelessly lost!");
                    235:                        goto retry;
                    236:                } else if (ntries == 3) {
                    237:                        printf("\rOops, still lost, quitting ...\r\n");
                    238:                        finish(1);
                    239:                }
                    240:        }
                    241: 
                    242:        upper = start;
                    243:        lower = upper + w->w_height - 1;        /* Don't include modeline */
                    244:        des_p = &DesiredScreen[upper];
                    245:        phys_p = &PhysScreen[upper];
                    246:        for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) {
                    247:                des_p->s_window = w;
                    248:                des_p->s_lp = lp;
                    249:                des_p->s_id = lp->l_dline & ~DIRTY;
                    250:                des_p->s_flags = isdirty(lp) ? L_MOD : 0;
                    251:                if (w->w_numlines)
                    252:                        des_p->s_vln = w->w_topnum + (i - upper);
                    253:                else
                    254:                        des_p->s_vln = 0;
                    255: 
                    256:                if (lp == w->w_line) {
                    257:                        int     diff = w->w_numlines ? 8 : 0,
                    258:                                strt_col = phys_p->s_offset,
                    259:                                end_col = strt_col + (CO - 2) - diff;
                    260: 
                    261:                        /* Right now we are displaying from strt_col to
                    262:                           end_col of the buffer line.  These are PRINT
                    263:                           colums, not actual characters. */
                    264:                        w->w_dotline = i;
                    265:                        w->w_dotcol = find_pos(lp, w->w_char);
                    266:                        /* if the new dotcol is out of range, reselect
                    267:                           a horizontal window */
                    268:                        if (w->w_dotcol < strt_col || w->w_dotcol >= end_col) {
                    269:                                if (w->w_dotcol < ((CO - 2) - diff))
                    270:                                        strt_col = 0;
                    271:                                else
                    272:                                        strt_col = w->w_dotcol - (CO / 2);
                    273:                        }
                    274:                        w->w_dotcol += diff;
                    275:                        des_p->s_offset = strt_col;
                    276:                        DotIsHere++;
                    277:                } else
                    278:                        des_p->s_offset = 0;
                    279:        }
                    280:        if (!DotIsHere) {
                    281:                f_mess("DotNotHere is impossible!");
                    282:                finish(1);
                    283:        }
                    284: 
                    285:        /* Is structure assignment faster than copy each field seperately */
                    286:        if (i < lower) {
                    287:                static struct scrimage  dirty_plate = { 0, DIRTY, 0, 0, 0, 0 },
                    288:                                        clean_plate = { 0, 0, 0, 0, 0, 0 };
                    289: 
                    290:                for (; i < lower; i++, des_p++, phys_p++)
                    291:                        if (phys_p->s_id != 0)
                    292:                                *des_p = dirty_plate;
                    293:                        else
                    294:                                *des_p = clean_plate;
                    295:        }
                    296: 
                    297:        des_p->s_window = w;
                    298:        des_p->s_flags = 0;
                    299:        if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine)
                    300:                des_p->s_flags = MODELINE | DIRTY;
                    301: }
                    302: 
                    303: /* Write whatever is in mesgbuf (maybe we are Asking, or just printed
                    304:    a message).  Turns off the UpdateMesg line flag. */
                    305: 
                    306: DrawMesg(abortable)
                    307: {
                    308:        if (charp())
                    309:                return;
                    310:        i_set(ILI, 0);
                    311:        if (swrite(mesgbuf, NIL, abortable)) {
                    312:                cl_eol();
                    313:                UpdMesg = 0;
                    314:        }
                    315:        flusho();
                    316: }
                    317: 
                    318: /* Goto the current position in the current window.  Presumably redisplay()
                    319:    has already been called, and curwind->{w_dotline,w_dotcol} have been set
                    320:    correctly. */
                    321: 
                    322: GotoDot()
                    323: {
                    324:        if (InputPending)
                    325:                return;
                    326:        Placur(curwind->w_dotline, curwind->w_dotcol -
                    327:                                PhysScreen[curwind->w_dotline].s_offset);
                    328:        flusho();
                    329: }
                    330: 
                    331: private
                    332: UntilEqual(start)
                    333: register int   start;
                    334: {
                    335:        register struct scrimage        *des_p = &DesiredScreen[start],
                    336:                                        *phys_p = &PhysScreen[start];
                    337: 
                    338:        while ((start < ILI) && (des_p->s_id != phys_p->s_id)) {
                    339:                des_p++;
                    340:                phys_p++;
                    341:                start++;
                    342:        }
                    343: 
                    344:        return start;
                    345: }
                    346: 
                    347: /* Calls the routine to do the physical changes, and changes PhysScreen to
                    348:    reflect those changes. */
                    349: 
                    350: AddLines(at, num)
                    351: register int   at,
                    352:                num;
                    353: {
                    354:        register  int   i;
                    355:        int     bottom = UntilEqual(at + num);
                    356: 
                    357:        if (num == 0 || num >= ((bottom - 1) - at))
                    358:                return 0;       /* We did nothing */
                    359:        v_ins_line(num, at, bottom - 1);
                    360: 
                    361:        /* Now change PhysScreen to account for the physical change. */
                    362: 
                    363:        for (i = bottom - 1; i - num >= at; i--)
                    364:                PhysScreen[i] = PhysScreen[i - num];
                    365:        for (i = 0; i < num; i++)
                    366:                PhysScreen[at + i].s_id = 0;
                    367:        return 1;       /* We did something. */
                    368: }
                    369: 
                    370: DelLines(at, num)
                    371: register int   at,
                    372:                num;
                    373: {
                    374:        register int    i;
                    375:        int     bottom = UntilEqual(at + num);
                    376: 
                    377:        if (num == 0 || num >= ((bottom - 1) - at))
                    378:                return 0;
                    379:        v_del_line(num, at, bottom - 1);
                    380: 
                    381:        for (i = at; num + i < bottom; i++)
                    382:                PhysScreen[i] = PhysScreen[num + i];
                    383:        for (i = bottom - num; i < bottom; i++)
                    384:                PhysScreen[i].s_id = 0;
                    385:        return 1;
                    386: }
                    387: 
                    388: /* Update line linenum in window w.  Only set PhysScreen to DesiredScreen
                    389:    if the swrite or cl_eol works, that is nothing is interupted by 
                    390:    characters typed. */ 
                    391: 
                    392: UpdLine(linenum)
                    393: register int   linenum;
                    394: {
                    395:        register struct scrimage        *des_p = &DesiredScreen[linenum];
                    396:        register Window *w = des_p->s_window;
                    397: 
                    398:        i_set(linenum, 0);
                    399:        if (des_p->s_flags & MODELINE)
                    400:                ModeLine(w);
                    401:        else if (des_p->s_id) {
                    402:                des_p->s_lp->l_dline &= ~DIRTY;
                    403:                des_p->s_flags &= ~(DIRTY | L_MOD);
                    404: #ifdef ID_CHAR
                    405:                if (!UseIC && w->w_numlines)
                    406: #else
                    407:                if (w->w_numlines)
                    408: #endif
                    409:                        (void) swrite(sprint("%6d  ", des_p->s_vln), NIL, YES);
                    410: 
                    411: #ifdef ID_CHAR
                    412:                if (UseIC) {
                    413:                        char    outbuf[256],
                    414:                                *lptr;
                    415:                        int     fromcol = w->w_numlines ? 8 : 0;
                    416: 
                    417:                        if (w->w_numlines)
                    418:                                sprintf(outbuf, "%6d  ", des_p->s_vln);
                    419:                        lptr = lcontents(des_p->s_lp);
                    420:                        DeTab(des_p->s_offset, lptr, outbuf + fromcol,
                    421:                                (sizeof outbuf) - 1 - fromcol,
                    422:                                des_p->s_window->w_visspace);
                    423:                        if (IDchar(outbuf, linenum, 0))
                    424:                                PhysScreen[linenum] = *des_p;
                    425:                        else if (i_set(linenum, 0), swrite(outbuf, NIL, YES))
                    426:                                do_cl_eol(linenum);
                    427:                        else
                    428:                                PhysScreen[linenum].s_id = -1;
                    429:                } else
                    430: #endif ID_CHAR
                    431:                    if (BufSwrite(linenum))
                    432:                        do_cl_eol(linenum);
                    433:                else
                    434:                        PhysScreen[linenum].s_id = -1;
                    435:        } else if (PhysScreen[linenum].s_id)    /* Not the same ... make sure */
                    436:                do_cl_eol(linenum);
                    437: }
                    438: 
                    439: do_cl_eol(linenum)
                    440: register int   linenum;
                    441: {
                    442:        cl_eol();
                    443:        PhysScreen[linenum] = DesiredScreen[linenum];
                    444: }
                    445: 
                    446: #ifdef ID_CHAR
                    447: 
                    448: /* From here to the end of the file is code that tries to utilize the
                    449:    insert/delete character feature on some terminals.  It is very confusing
                    450:    and not so well written code, AND there is a lot of it.  You may want
                    451:    to use the space for something else. */
                    452: 
                    453: extern struct screenline       *Screen;
                    454: int    IN_INSmode = 0;
                    455: 
                    456: int    UseIC;
                    457: 
                    458: int    DClen,
                    459:        MDClen,
                    460:        IClen,
                    461:        MIClen,
                    462:        IMlen,
                    463:        CElen;
                    464: 
                    465: disp_opt_init()
                    466: {
                    467:        DClen = DC ? strlen(DC) : 0;
                    468:        MDClen = M_DC ? strlen(M_DC) : 9999;
                    469:        IClen = IC ? strlen(IC) : 0;
                    470:        MIClen = M_IC ? strlen(M_IC) : 9999;
                    471:        IMlen = IM ? strlen(IM) : 0;
                    472:        CElen = CE ? strlen(CE) : 0;
                    473: 
                    474:        UseIC = (IC || IM || M_IC);
                    475: }
                    476: 
                    477: INSmode(on)
                    478: {
                    479:        if (on && !IN_INSmode) {
                    480:                putpad(IM, 1);
                    481:                IN_INSmode++;
                    482:        } else if (!on && IN_INSmode) {
                    483:                putpad(EI, 1);
                    484:                IN_INSmode = 0;
                    485:        }
                    486: }
                    487: 
                    488: private
                    489: DeTab(s_offset, buf, outbuf, limit, visspace)
                    490: register char  *buf;
                    491: char   *outbuf;
                    492: {
                    493:        register char   *phys_p = outbuf,
                    494:                        c;
                    495:        register int    pos = 0;
                    496:        char            *limitp = &outbuf[limit];
                    497: 
                    498: #define OkayOut(ch)    if ((pos++ >= s_offset) && (phys_p < limitp))\
                    499:                                *phys_p++ = ch;\
                    500:                        else
                    501: 
                    502:        while (c = *buf++) {
                    503:                if (c == '\t') {
                    504:                        int     nchars = (tabstop - (pos % tabstop));
                    505: 
                    506:                        if (visspace) {
                    507:                                OkayOut('>');
                    508:                                --nchars;
                    509:                        }
                    510:                        while (--nchars >= 0)
                    511:                                OkayOut(' ');
                    512: 
                    513:                } else if (isctrl(c)) {
                    514:                        OkayOut('^');
                    515:                        OkayOut(c == 0177 ? '?' : c + '@');
                    516:                } else {
                    517:                        if (visspace && c == ' ')
                    518:                                c = '_';
                    519:                        OkayOut(c);
                    520:                }
                    521:                if (pos - s_offset >= CO) {
                    522:                        phys_p = &outbuf[CO - 1];
                    523:                        *phys_p++ = '!';
                    524:                        break;
                    525:                }                       
                    526:        }
                    527:        *phys_p = 0;
                    528: }
                    529: 
                    530: /* ID character routines full of special cases and other fun stuff like that.
                    531:    It actually works though ... 
                    532: 
                    533:        Returns Non-Zero if you are finished (no differences left). */
                    534: 
                    535: private
                    536: IDchar(new, lineno, col)
                    537: register char  *new;
                    538: {
                    539:        register int    i;
                    540:        int     j,
                    541:                oldlen,
                    542:                NumSaved;
                    543:        register struct screenline      *sline = &Screen[lineno];
                    544: 
                    545:        oldlen = sline->s_length - sline->s_line;
                    546: 
                    547:        for (i = col; i < oldlen && new[i] != 0; i++)
                    548:                if (sline->s_line[i] != new[i])
                    549:                        break;
                    550:        if (new[i] == 0 || i == oldlen)
                    551:                return (new[i] == 0 && i == oldlen);
                    552: 
                    553:        for (j = i + 1; j < oldlen && new[j]; j++) {
                    554:                if (new[j] == sline->s_line[i]) {
                    555:                        NumSaved = IDcomp(new + j, sline->s_line + i,
                    556:                                        strlen(new)) + NumSimilar(new + i,
                    557:                                                sline->s_line + i, j - i);
                    558:                        if (OkayInsert(NumSaved, j - i)) {
                    559:                                InsChar(lineno, i, j - i, new);
                    560:                                return(IDchar(new, lineno, j));
                    561:                        }
                    562:                }
                    563:        }
                    564: 
                    565:        for (j = i + 1; j < oldlen && new[i]; j++) {
                    566:                if (new[i] == sline->s_line[j]) {
                    567:                        NumSaved = IDcomp(new + i, sline->s_line + j,
                    568:                                        oldlen - j);
                    569:                        if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) {
                    570:                                DelChar(lineno, i, j - i);
                    571:                                return(IDchar(new, lineno, j));
                    572:                        }
                    573:                }
                    574:        }
                    575:        return 0;
                    576: }
                    577: 
                    578: private
                    579: NumSimilar(s, t, n)
                    580: register char  *s,
                    581:                *t;
                    582: {
                    583:        register int    num = 0;
                    584: 
                    585:        while (n--)
                    586:                if (*s++ == *t++)
                    587:                        num++;
                    588:        return num;
                    589: }
                    590: 
                    591: private
                    592: IDcomp(s, t, len)
                    593: register char  *s,
                    594:                *t;
                    595: {
                    596:        register int    i;
                    597:        int     num = 0,
                    598:                nonspace = 0;
                    599:        char    c;
                    600: 
                    601:        for (i = 0; i < len; i++) {
                    602:                if ((c = *s++) != *t++)
                    603:                        break;
                    604:                if (c != ' ')
                    605:                        nonspace++;
                    606:                if (nonspace)
                    607:                        num++;
                    608:        }
                    609: 
                    610:        return num;
                    611: }
                    612: 
                    613: private
                    614: OkayDelete(Saved, num, samelength)
                    615: {
                    616:        /* If the old and the new are the same length, then we don't
                    617:         * have to clear to end of line.  We take that into consideration.
                    618:         */
                    619:        return ((Saved + (!samelength ? CElen : 0))
                    620:                > min(MDClen, DClen * num));
                    621: }
                    622: 
                    623: private
                    624: OkayInsert(Saved, num)
                    625: {
                    626:        register int    n = 0;
                    627: 
                    628:        if (IC)         /* Per character prefixes */
                    629:                n = min(num * IClen, MIClen);
                    630: 
                    631:        if (IM && !IN_INSmode) {        
                    632:                /* Good terminal.  Fewer characters in this case */
                    633:                n += IMlen;
                    634:        }
                    635: 
                    636:        n += num;       /* The characters themselves */
                    637: 
                    638:        return Saved > n;
                    639: }
                    640: 
                    641: extern int     CapCol;
                    642: extern char    *cursend;
                    643: extern struct screenline       *Curline;
                    644: 
                    645: private
                    646: DelChar(lineno, col, num)
                    647: {
                    648:        register char   *from,
                    649:                        *to;
                    650:        register int    i;
                    651:        struct screenline *sp = (&Screen[lineno]);
                    652: 
                    653:        Placur(lineno, col);
                    654:        if (M_DC && num > 1) {
                    655:                char    minibuf[16];
                    656: 
                    657:                sprintf(minibuf, M_DC, num);
                    658:                putpad(minibuf, num);
                    659:        } else {
                    660:                for (i = num; --i >= 0; )
                    661:                        putpad(DC, 1);
                    662:        }
                    663: 
                    664:        to = sp->s_line + col;
                    665:        from = to + num;
                    666: 
                    667:        byte_copy(from, to, sp->s_length - from + 1);
                    668:        clrline(sp->s_length - num, sp->s_length);
                    669:        sp->s_length -= num;
                    670: }
                    671: 
                    672: private
                    673: InsChar(lineno, col, num, new)
                    674: char   *new;
                    675: {
                    676:        register char   *sp1,
                    677:                        *sp2,   /* To push over the array. */
                    678:                        *sp3;   /* Last character to push over. */
                    679:        int     i;
                    680: 
                    681:        i_set(lineno, 0);
                    682:        sp2 = Curline->s_length + num;
                    683: 
                    684:        if (sp2 >= cursend) {
                    685:                i_set(lineno, CO - num - 1);
                    686:                cl_eol();
                    687:                sp2 = cursend - 1;
                    688:        }
                    689:        Curline->s_length = sp2;
                    690:        sp1 = sp2 - num;
                    691:        sp3 = Curline->s_line + col;
                    692: 
                    693:        while (sp1 >= sp3)
                    694:                *sp2-- = *sp1--;
                    695: 
                    696:        new += col;
                    697:        byte_copy(new, sp3, num);
                    698:        /* The internal screen is correct, and now we have to do
                    699:           the physical stuff. */
                    700: 
                    701:        Placur(lineno, col);
                    702:        if (IM) {
                    703:                if (!IN_INSmode)
                    704:                        INSmode(1);
                    705:        } else if (M_IC && num > 1) {
                    706:                char    minibuf[16];
                    707: 
                    708:                sprintf(minibuf, M_IC, num);
                    709:                putpad(minibuf, num);
                    710:        } else if (IC) {
                    711:                for (i = 0; i < num; i++)
                    712:                        putpad(IC, 1);
                    713:        }
                    714:        for (i = 0; i < num; i++) {
                    715:                putchar(new[i]);
                    716:                if (IN_INSmode)
                    717:                        putpad(IP, 1);
                    718:        }
                    719:        CapCol += num;
                    720: }
                    721: 
                    722: #endif ID_CHAR
                    723: 
                    724: /* chkmail() returns nonzero if there is new mail since the
                    725:    last time we checked. */
                    726: 
                    727: char   Mailbox[128];   /* initialized in main */
                    728: int    MailInt = 60;   /* check no more often than 60 seconds */
                    729: #ifdef BIFF
                    730: int    BiffChk = NO;   /* whether or not to turn off biff while in JOVE */
                    731: #endif
                    732: 
                    733: chkmail(force)
                    734: {
                    735:        time_t  now;
                    736:        static time_t   last_chk = 0;
                    737:        static int      value = FALSE;
                    738:        static off_t    last_size = 0;
                    739:        struct stat     stbuf;
                    740:        int     last_val;
                    741:        extern time_t   time0;
                    742: 
                    743:        time(&now);
                    744:        if (!force && (now < last_chk + MailInt))
                    745:                return value;
                    746:        if (stat(Mailbox, &stbuf) < 0)
                    747:                return FALSE;
                    748:        last_val = value;
                    749:        value = ((stbuf.st_mtime > time0) &&
                    750:                 (stbuf.st_size > 0) &&
                    751:                 (stbuf.st_size > last_size) &&
                    752:                 (stbuf.st_mtime + 5 > stbuf.st_atime));
                    753:        last_chk = now;
                    754:        last_size = stbuf.st_size;
                    755:        if (value == TRUE && value != last_val)
                    756:                dobell(3);
                    757:        return value;
                    758: }
                    759: 
                    760: /* Print the mode line. */
                    761: 
                    762: private char   *mode_p,
                    763:                *mend_p;
                    764: int    BriteMode = 1;          /* modeline should standout */
                    765: 
                    766: private
                    767: mode_app(str)
                    768: register char  *str;
                    769: {
                    770:        if (mode_p >= mend_p)
                    771:                return;
                    772:        while ((mode_p < mend_p) && (*mode_p++ = *str++))
                    773:                ;
                    774:        mode_p--;       /* back over the null */
                    775: }
                    776: 
                    777: char   ModeFmt[120] = "%3c %[%sJOVE (%M)   Buffer: %b  \"%f\" %]%s%m %((%t)%s%)%e";
                    778: 
                    779: ModeLine(w)
                    780: register Window        *w;
                    781: {
                    782:        extern int      i_line;
                    783:        int     n,
                    784:                ign_some = 0;
                    785:        char    line[132],
                    786:                *fmt = ModeFmt,
                    787:                tmp[16],
                    788:                fillc,
                    789:                c;
                    790:        register Buffer *thisbuf = w->w_bufp;
                    791:        register Buffer *bp;
                    792: 
                    793:        mode_p = line;
                    794:        mend_p = &line[(sizeof line) - 1];
                    795: 
                    796:        if (BriteMode != 0 && SO == 0)
                    797:                BriteMode = 0;
                    798:        fillc = BriteMode ? ' ' : '-';
                    799: 
                    800:        while (c = *fmt++) {
                    801:                if (c == '\\')
                    802:                        c = *fmt++;
                    803:                if (c != '%') {
                    804:                        if (!ign_some)
                    805:                                *mode_p++ = c;
                    806:                        continue;
                    807:                }
                    808:                c = *fmt++;     /* Character after the percent! */
                    809:                if (ign_some && c != ')')
                    810:                        continue;
                    811:                n = 1;
                    812:                if (c >= '0' && c <= '9') {
                    813:                        n = 0;
                    814:                        while (c >= '0' && c <= '9') {
                    815:                                n = n * 10 + (c - '0');
                    816:                                c = *fmt++;
                    817:                        }
                    818:                }
                    819:                switch (c) {
                    820:                case '(':
                    821:                        if (w->w_next != fwind) /* Not bottom window. */
                    822:                                ign_some++;
                    823:                        break;
                    824: 
                    825:                case ')':
                    826:                        ign_some = 0;
                    827:                        break;
                    828: 
                    829:                case 'c':
                    830:                        while (--n >= 0)
                    831:                                *mode_p++ = fillc;
                    832:                        break;
                    833: 
                    834:                case '[':
                    835:                case ']':
                    836:                    {
                    837:                        char    *strs = (c == '[') ? "[[[[[[[[[[" : "]]]]]]]]]]";
                    838: 
                    839:                        mode_app(strs + 10 - RecDepth);
                    840:                        break;
                    841:                    }
                    842:                        
                    843:                case 's':
                    844:                        if (mode_p[-1] == ' ')
                    845:                                continue;
                    846:                        *mode_p++ = ' ';
                    847:                        break;
                    848: 
                    849:                case 'M':
                    850:                    {
                    851:                        static char     *mmodes[] = {
                    852:                                "Fundamental ",
                    853:                                "Text ",
                    854:                                "C ",
                    855: #ifdef LISP
                    856:                                "Lisp ",
                    857: #endif
                    858:                                0
                    859:                        };
                    860: 
                    861:                        mode_app(mmodes[thisbuf->b_major]);
                    862: 
                    863:                        if (BufMinorMode(thisbuf, Fill))
                    864:                                mode_app("Fill ");
                    865:                        if (BufMinorMode(thisbuf, Abbrev))
                    866:                                mode_app("Abbrev ");
                    867:                        if (BufMinorMode(thisbuf, OverWrite))
                    868:                                mode_app("OvrWt ");
                    869:                        if (BufMinorMode(thisbuf, Indent))
                    870:                                mode_app("AI ");
                    871:                        if (KeyMacro.m_flags & DEFINE)
                    872:                                mode_app("Def ");
                    873:                        mode_p--;       /* Back over the extra space. */
                    874:                        break;
                    875:                    }
                    876: 
                    877:                case 'b':
                    878:                        mode_app(thisbuf->b_name);
                    879:                        break;
                    880: 
                    881:                case 'f':
                    882:                case 'F':
                    883:                        if (thisbuf->b_fname == 0)
                    884:                                mode_app("[No file]");
                    885:                        else {
                    886:                                if (c == 'f')
                    887:                                        mode_app(pr_name(thisbuf->b_fname));
                    888:                                else
                    889:                                        mode_app(basename(thisbuf->b_fname));
                    890:                        }
                    891:                        break;
                    892: 
                    893: 
                    894:                case 'n':
                    895:                        for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++)
                    896:                                if (bp == thisbuf)
                    897:                                        break;
                    898: 
                    899:                        sprintf(tmp, "%d", n);
                    900:                        mode_app(tmp);
                    901:                        break;
                    902: 
                    903:                case 'm':
                    904:                        if (IsModified(w->w_bufp))
                    905:                                *mode_p++ = '*';
                    906:                        else
                    907:                                *mode_p++ = ' ';
                    908:                        break;
                    909: 
                    910:                case 't':
                    911:                    {
                    912:                        char    timestr[12];
                    913: 
                    914:                        mode_app(get_time((time_t *) 0, timestr, 11, 16));
                    915:                        break;
                    916:                    }
                    917: 
                    918: #ifdef LOAD_AV
                    919:                case 'l':
                    920:                    {
                    921:                        double  theavg;
                    922:                        char    minibuf[10];
                    923: 
                    924:                        get_la(&theavg);
                    925:                        theavg += .005; /* round to nearest .01 */
                    926:                        sprintf(minibuf, "%d.%02d",
                    927:                               (int) theavg,
                    928:                               (int)((theavg - (int) theavg) * 100));
                    929:                        mode_app(minibuf);
                    930:                    }
                    931:                    break;
                    932: #endif
                    933: 
                    934:                case 'C':       /* check mail here */
                    935:                        if (chkmail(NO))
                    936:                                mode_app("[New mail]");
                    937:                        break;
                    938: 
                    939: #ifdef CHDIR
                    940:                case 'd':       /* print working directory */
                    941:                        mode_app(pr_name(pwd()));
                    942:                        break;
                    943: #endif
                    944:                        
                    945:                case 'e':
                    946:                    {
                    947:                        /* 2 space pad pluss padding for magic cookies */
                    948:                        char    *last_p = &line[CO - 2 - (2 * SG)];
                    949: 
                    950:                        while (mode_p < last_p)
                    951:                                *mode_p++ = fillc;
                    952: 
                    953:                        goto outahere;          /* %e means we're done! */
                    954:                    }
                    955:                }
                    956:        }
                    957: 
                    958: outahere:
                    959:        *mode_p = 0;
                    960: 
                    961:        /* Highlight mode line. */
                    962:        if (BriteMode) {
                    963: #ifdef ID_CHAR
                    964:                if (IN_INSmode)
                    965:                        INSmode(0);
                    966: #endif
                    967:                putpad(SO, 1);
                    968:        }
                    969:        if (swrite(line, BriteMode, YES))
                    970:                do_cl_eol(i_line);
                    971:        if (BriteMode)
                    972:                putpad(SE, 1);
                    973: }
                    974: 
                    975: RedrawDisplay()
                    976: {
                    977:        Line    *newtop = prev_line((curwind->w_line = curline), exp_p ?
                    978:                                exp : HALF(curwind));
                    979: 
                    980:        if (newtop == curwind->w_top)
                    981:                v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind));
                    982:        else
                    983:                SetTop(curwind, newtop);
                    984: }
                    985: 
                    986: v_clear(line1, line2)
                    987: register int   line1;
                    988: {
                    989:        register struct scrimage        *phys_p, *des_p;
                    990: 
                    991:        phys_p = &PhysScreen[line1];
                    992:        des_p = &DesiredScreen[line1];
                    993: 
                    994:        while (line1 <= line2) {
                    995:                i_set(line1++, 0);
                    996:                cl_eol();
                    997:                phys_p->s_id = des_p->s_id = 0;
                    998:                phys_p++, des_p++;
                    999:        }
                   1000: }
                   1001: 
                   1002: ClAndRedraw()
                   1003: {
                   1004:        cl_scr(1);
                   1005: }
                   1006: 
                   1007: NextPage()
                   1008: {
                   1009:        Line    *newline;
                   1010: 
                   1011:        if (Asking)
                   1012:                return;
                   1013:        if (exp < 0) {
                   1014:                exp = -exp;
                   1015:                PrevPage();
                   1016:                return;
                   1017:        }
                   1018:        if (exp_p)
                   1019:                UpScroll();
                   1020:        else {
                   1021:                if (in_window(curwind, curwind->w_bufp->b_last) != -1) {
                   1022:                        rbell();
                   1023:                        return;
                   1024:                }
                   1025:                newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1));
                   1026:                SetTop(curwind, curwind->w_line = newline);
                   1027:                if (curwind->w_bufp == curbuf)
                   1028:                        SetLine(newline);
                   1029:        }
                   1030: }
                   1031: 
                   1032: PrevPage()
                   1033: {
                   1034:        Line    *newline;
                   1035: 
                   1036:        if (Asking)
                   1037:                return;
                   1038:        if (exp < 0) {
                   1039:                exp = -exp;
                   1040:                NextPage();
                   1041:                return;
                   1042:        }
                   1043:        if (exp_p)
                   1044:                DownScroll();
                   1045:        else {
                   1046:                newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1));
                   1047:                SetTop(curwind, curwind->w_line = newline);
                   1048:                if (curwind->w_bufp == curbuf)
                   1049:                        SetLine(newline);
                   1050:        }
                   1051: }
                   1052: 
                   1053: UpScroll()
                   1054: {
                   1055:        SetTop(curwind, next_line(curwind->w_top, exp));
                   1056:        if ((curwind->w_bufp == curbuf) &&
                   1057:            (in_window(curwind, curline) == -1))
                   1058:                SetLine(curwind->w_top);
                   1059: }
                   1060: 
                   1061: DownScroll()
                   1062: {
                   1063:        SetTop(curwind, prev_line(curwind->w_top, exp));
                   1064:        if ((curwind->w_bufp == curbuf) &&
                   1065:            (in_window(curwind, curline) == -1))
                   1066:                SetLine(curwind->w_top);
                   1067: }
                   1068: 
                   1069: int    VisBell = 0,
                   1070:        RingBell = 0;   /* So if we have a lot of errors ...
                   1071:                           ring the bell only ONCE */
                   1072: rbell()
                   1073: {
                   1074:        RingBell++;
                   1075: }
                   1076: 
                   1077: /* Message prints the null terminated string onto the bottom line of the
                   1078:    terminal. */
                   1079: 
                   1080: message(str)
                   1081: char   *str;
                   1082: {
                   1083:        if (InJoverc)
                   1084:                return;
                   1085:        UpdMesg++;
                   1086:        errormsg = 0;
                   1087:        if (str != mesgbuf)
                   1088:                null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1);
                   1089: }
                   1090: 
                   1091: /* End of Window */
                   1092: 
                   1093: Eow()
                   1094: {
                   1095:        if (Asking)
                   1096:                return;
                   1097:        SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 -
                   1098:                        min(SIZE(curwind) - 1, exp - 1)));
                   1099:        if (!exp_p)
                   1100:                Eol();
                   1101: }
                   1102: 
                   1103: /* Beginning of Window */
                   1104: 
                   1105: Bow()
                   1106: {
                   1107:        if (Asking)
                   1108:                return;
                   1109:        SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, exp - 1)));
                   1110: }
                   1111: 
                   1112: private int    LineNo,
                   1113:                last_col,
                   1114:                DoAutoNL;
                   1115: private Window *old_wind;      /* save the window we were in BEFORE
                   1116:                                   before we were called, if UseBuffers
                   1117:                                   is nonzero */
                   1118: 
                   1119: int    UseBuffers = FALSE;
                   1120: int    TOabort = 0;
                   1121: 
                   1122: /* This initializes the typeout.  If send-typeout-to-buffers is set
                   1123:    the buffer NAME is created (emptied if it already exists) and output
                   1124:    goes to the buffer.  Otherwise output is drawn on the screen and
                   1125:    erased by TOstop() */
                   1126: 
                   1127: TOstart(name, auto_newline)
                   1128: char   *name;
                   1129: {
                   1130:        if (UseBuffers) {
                   1131:                old_wind = curwind;
                   1132:                pop_wind(name, YES, B_SCRATCH);
                   1133:        }
                   1134:        TOabort = LineNo = last_col = 0;
                   1135:        DoAutoNL = auto_newline;
                   1136: }
                   1137: 
                   1138: /* VARARGS1 */
                   1139: 
                   1140: Typeout(fmt, va_alist)
                   1141: char   *fmt;
                   1142: va_dcl
                   1143: {
                   1144:        if (TOabort)
                   1145:                return;
                   1146: 
                   1147:        if (!UseBuffers && (LineNo == ILI - 1)) {
                   1148:                register int    c;
                   1149: 
                   1150:                LineNo = 0;
                   1151:                last_col = 0;
                   1152:                f_mess("--more--");
                   1153:                if ((c = getchar()) != ' ') {
                   1154:                        TOabort++;
                   1155:                        if (c != CTL(G) && c != RUBOUT)
                   1156:                                Ungetc(c);
                   1157:                        return;
                   1158:                }
                   1159:                f_mess(NullStr);
                   1160:        }
                   1161: 
                   1162:        if (fmt) {
                   1163:                extern int      i_col;
                   1164:                char    string[132];
                   1165:                va_list ap;
                   1166: 
                   1167:                va_start(ap);
                   1168:                format(string, sizeof string, fmt, ap);
                   1169:                va_end(ap);
                   1170:                if (UseBuffers)
                   1171:                        ins_str(string, NO);
                   1172:                else {
                   1173:                        i_set(LineNo, last_col);
                   1174:                        (void) swrite(string, NIL, YES);
                   1175:                        last_col = i_col;
                   1176:                }
                   1177:        }
                   1178:        if (!UseBuffers) {
                   1179:                PhysScreen[LineNo].s_id = -1;
                   1180:                if (fmt == 0 || DoAutoNL != 0) {
                   1181:                        cl_eol();
                   1182:                        flusho();
                   1183:                        LineNo++;
                   1184:                        last_col = 0;
                   1185:                }
                   1186:        } else if (fmt == 0 || DoAutoNL != 0)
                   1187:                ins_str("\n", NO);
                   1188: }
                   1189: 
                   1190: TOstop()
                   1191: {
                   1192:        int     c;
                   1193: 
                   1194:        if (UseBuffers) {
                   1195:                ToFirst();
                   1196:                SetWind(old_wind);
                   1197:        } else {
                   1198:                if (TOabort)
                   1199:                        return;
                   1200:                if (last_col != 0)
                   1201:                        Typeout((char *) 0);
                   1202:                Typeout("----------");
                   1203:                cl_eol();
                   1204:                flusho();
                   1205:                c = getchar();
                   1206:                if (c != ' ')
                   1207:                        Ungetc(c);
                   1208:        }
                   1209: }

unix.superglobalmegacorp.com

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