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

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: #include "jove.h"
                      9: #include "ctype.h"
                     10: #include "termcap.h"
                     11: #include "chars.h"
                     12: #include "fp.h"
                     13: #include "disp.h"
                     14: #if defined(IPROCS)
                     15: # include "iproc.h"
                     16: #endif
                     17: 
                     18: #ifdef MAC
                     19: # include "mac.h"
                     20: #else
                     21: # ifdef        STDARGS
                     22: #  include <stdarg.h>
                     23: # else
                     24: #  include <varargs.h>
                     25: # endif
                     26: # include <sys/stat.h>
                     27: #endif
                     28: 
                     29: #include <signal.h>
                     30: 
                     31: private void
                     32: #ifdef ID_CHAR
                     33:        DeTab proto((int, char *, char *, size_t, int)),
                     34:        DelChar proto((int, int, int)),
                     35:        InsChar proto((int, int, int, char *)),
                     36: #endif
                     37:        DoIDline proto((int)),
                     38:        do_cl_eol proto((int)),
                     39:        ModeLine proto((Window *)),
                     40:        GotoDot proto((void)),
                     41:        UpdLine proto((int)),
                     42:        UpdWindow proto((Window *, int));
                     43: 
                     44: #ifdef MSDOS
                     45: extern void    dobell proto((int x));
                     46: #else
                     47: private void   dobell proto((int x));
                     48: #endif
                     49: 
                     50: private int
                     51: #ifdef ID_CHAR
                     52:        IDchar proto ((char *, int, int)),
                     53:        NumSimilar proto ((char *, char *, int)),
                     54:        IDcomp proto ((char *, char *, int)),
                     55:        OkayDelete proto ((int, int, int)),
                     56:        OkayInsert proto ((int, int)),
                     57: #endif
                     58:        AddLines proto((int, int)),
                     59:        DelLines proto((int, int)),
                     60:        UntilEqual proto((int));
                     61: 
                     62: 
                     63: 
                     64: int    DisabledRedisplay = NO;
                     65: 
                     66: /* Kludge windows gets called by the routines that delete lines from the
                     67:    buffer.  If the w->w_line or w->w_top are deleted and this procedure
                     68:    is not called, the redisplay routine will barf. */
                     69: 
                     70: void
                     71: ChkWindows(line1, line2)
                     72: Line   *line1;
                     73: register Line  *line2;
                     74: {
                     75:        register Window *w = fwind;
                     76:        register Line   *lp;
                     77: 
                     78:        do {
                     79:                for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) {
                     80:                        if (lp == w->w_top)
                     81:                                w->w_flags |= W_TOPGONE;
                     82:                        if (lp == w->w_line)
                     83:                                w->w_flags |= W_CURGONE;
                     84:                }
                     85:                w = w->w_next;
                     86:        } while (w != fwind);
                     87: }
                     88: 
                     89: private int    RingBell;       /* So if we have a lot of errors ...
                     90:                                  ring the bell only ONCE */
                     91: 
                     92: void
                     93: redisplay()
                     94: {
                     95:        register Window *w = fwind;
                     96:        int     lineno,
                     97:                done_ID = NO,
                     98:                i;
                     99:        register struct scrimage        *des_p,
                    100:                                        *phys_p;
                    101: 
                    102:        if (DisabledRedisplay == YES)
                    103:                return;
                    104:        curwind->w_line = curwind->w_bufp->b_dot;
                    105:        curwind->w_char = curwind->w_bufp->b_char;
                    106: #ifdef MAC
                    107:        InputPending = 0;
                    108: #else
                    109:        if ((InputPending = charp()) != '\0')   /* calls CheckEvent, which could */
                    110:                return; /* result in a call to rediplay(). We don't want that. */
                    111: #endif
                    112: #ifdef JOB_CONTROL
                    113:        if (UpdFreq)
                    114:                SigHold(SIGALRM);
                    115: #endif
                    116:        if (RingBell) {
                    117:                dobell(1);
                    118:                RingBell = 0;
                    119:        }
                    120:        AbortCnt = BufSize;             /* initialize this now */
                    121:        if (UpdMesg)
                    122:                DrawMesg(YES);
                    123: 
                    124:        for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
                    125:                UpdWindow(w, lineno);
                    126:                lineno += w->w_height;
                    127:        }
                    128: 
                    129:        UpdModLine = 0; /* Now that we've called update window, we can
                    130:                           assume that the modeline will be updated.  But
                    131:                           if while redrawing the modeline the user types
                    132:                           a character, ModeLine() is free to set this on
                    133:                           again so that the modeline will be fully drawn
                    134:                           at the next redisplay. */
                    135: 
                    136:        des_p = DesiredScreen;
                    137:        phys_p = PhysScreen;
                    138:        for (i = 0; i < ILI; i++, des_p++, phys_p++) {
                    139:                if (!done_ID && (des_p->s_id != phys_p->s_id)) {
                    140:                        DoIDline(i);
                    141:                        done_ID = YES;
                    142:                }
                    143:                if ((des_p->s_flags & (DIRTY | L_MOD)) ||
                    144:                    (des_p->s_id != phys_p->s_id) ||
                    145:                    (des_p->s_vln != phys_p->s_vln) ||
                    146:                    (des_p->s_offset != phys_p->s_offset))
                    147:                        UpdLine(i);
                    148:                if (InputPending)
                    149:                        goto ret;
                    150:        }
                    151: 
                    152:        if (Asking) {
                    153:                Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking)));
                    154:                        /* Nice kludge */
                    155:                flusho();
                    156:        } else
                    157:                GotoDot();
                    158: ret:
                    159: #ifdef JOB_CONTROL
                    160:        if (UpdFreq)
                    161:                SigRelse(SIGALRM);
                    162: #else
                    163:        ;       /* yuck */
                    164: #endif
                    165: #ifdef MAC
                    166:        if(Windchange) docontrols();
                    167: #endif /* MAC */
                    168: }
                    169: 
                    170: #ifndef IBMPC
                    171: private void
                    172: dobell(n)
                    173: int    n;
                    174: {
                    175:        while (--n >= 0) {
                    176: #ifndef MAC
                    177:                if (VisBell && VB)
                    178:                        putstr(VB);
                    179:                else
                    180:                        putpad(BL, 1);
                    181: #else
                    182:                SysBeep(5);
                    183: #endif
                    184:        }
                    185:        flusho();
                    186: }
                    187: #endif /* IBMPC */
                    188: 
                    189: /* find_pos() returns the position on the line, that C_CHAR represents
                    190:    in LINE */
                    191: 
                    192: int
                    193: find_pos(line, c_char)
                    194: Line   *line;
                    195: int    c_char;
                    196: {
                    197:        return calc_pos(lcontents(line), c_char);
                    198: }
                    199: 
                    200: int
                    201: calc_pos(lp, c_char)
                    202: register char  *lp;
                    203: register int   c_char;
                    204: {
                    205:        register int    pos = 0;
                    206:        register int    c;
                    207: 
                    208: 
                    209:        while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {
                    210:                if (c == '\t')
                    211:                        pos += (tabstop - (pos % tabstop));
                    212:                else if (isctrl(c))
                    213:                        pos += 2;
                    214:                else
                    215:                        pos += 1;
                    216:        }
                    217:        return pos;
                    218: }
                    219: 
                    220: int    UpdModLine = 0,
                    221:        UpdMesg = 0;
                    222: 
                    223: private void
                    224: DoIDline(start)
                    225: int    start;
                    226: {
                    227:        register struct scrimage        *des_p = &DesiredScreen[start];
                    228:        struct scrimage *phys_p = &PhysScreen[start];
                    229:        register int    i,
                    230:                        j;
                    231: 
                    232:        /* Some changes have been made.  Try for insert or delete lines.
                    233:           If either case has happened, Addlines and/or DelLines will do
                    234:           necessary scrolling, also CONVERTING PhysScreen to account for the
                    235:           physical changes.  The comparison continues from where the
                    236:           insertion/deletion takes place; this doesn't happen very often,
                    237:           usually it happens with more than one window with the same
                    238:           buffer. */
                    239: 
                    240:        if (!CanScroll)
                    241:                return;         /* We should never have been called! */
                    242: 
                    243:        for (i = start; i < ILI; i++, des_p++, phys_p++)
                    244:                if (des_p->s_id != phys_p->s_id)
                    245:                        break;
                    246: 
                    247:        for (; i < ILI; i++) {
                    248:                for (j = i + 1; j < ILI; j++) {
                    249:                        des_p = &DesiredScreen[j];
                    250:                        phys_p = &PhysScreen[j];
                    251:                        if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
                    252:                                break;
                    253:                        if (des_p->s_id == PhysScreen[i].s_id) {
                    254:                                if (des_p->s_id == 0)
                    255:                                        continue;
                    256:                                if (AddLines(i, j - i)) {
                    257:                                        DoIDline(j);
                    258:                                        return;
                    259:                                }
                    260:                                break;
                    261:                        }
                    262:                        if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
                    263:                                if (des_p->s_id == 0)
                    264:                                        continue;
                    265:                                if (DelLines(i, j - i)) {
                    266:                                        DoIDline(i);
                    267:                                        return;
                    268:                                }
                    269:                                break;
                    270:                        }
                    271:                }
                    272:        }
                    273: }
                    274: 
                    275: /* Make DesiredScreen reflect what the screen should look like when we are done
                    276:    with the redisplay.  This deals with horizontal scrolling.  Also makes
                    277:    sure the current line of the Window is in the window. */
                    278: 
                    279: int    ScrollAll = NO;
                    280: 
                    281: private void
                    282: UpdWindow(w, start)
                    283: register Window        *w;
                    284: int    start;
                    285: {
                    286:        Line    *lp;
                    287:        int     i,
                    288:                upper,          /* top of window */
                    289:                lower,          /* bottom of window */
                    290:                strt_col,       /* starting print column of current line */
                    291:                ntries = 0;     /* # of tries at updating window */
                    292:        register struct scrimage        *des_p,
                    293:                                        *phys_p;
                    294:        Buffer  *bp = w->w_bufp;
                    295: 
                    296: retry:
                    297:        if (w->w_flags & W_CURGONE) {
                    298:                w->w_line = bp->b_dot;
                    299:                w->w_char = bp->b_char;
                    300:        }
                    301:        if (w->w_flags & W_TOPGONE)
                    302:                CentWind(w);    /* reset topline of screen */
                    303:        w->w_flags &= ~(W_CURGONE | W_TOPGONE);
                    304: 
                    305:        /* make sure that the current line is in the window */
                    306:        upper = start;
                    307:        lower = upper + w->w_height - 1;        /* don't include modeline */
                    308:        for (i = upper, lp = w->w_top; i < lower && lp != 0; lp = lp->l_next, i++)
                    309:                if (lp == w->w_line)
                    310:                        break;
                    311:        if (i == lower || lp == 0) {
                    312:                ntries += 1;
                    313:                if (ntries == 1) {
                    314:                        CalcWind(w);
                    315:                        goto retry;
                    316:                } else if (ntries == 2) {
                    317:                        w->w_top = w->w_line = w->w_bufp->b_first;
                    318:                        writef("\rERROR in redisplay: I got hopelessly lost!");
                    319:                        dobell(2);
                    320:                        goto retry;
                    321:                } else if (ntries == 3) {
                    322:                        writef("\n\rOops, still lost, quitting ...\r\n");
                    323:                        finish(1);
                    324:                }
                    325:        }
                    326: 
                    327:        /* first do some calculations for the current line */
                    328:        {
                    329:                int     diff = (w->w_flags & W_NUMLINES) ? 8 : 0,
                    330:                        end_col;
                    331: 
                    332:                strt_col = (ScrollAll == YES) ? w->w_LRscroll :
                    333:                           PhysScreen[i].s_offset;
                    334:                end_col = strt_col + (CO - 2) - diff;
                    335:                /* Right now we are displaying from strt_col to
                    336:                   end_col of the buffer line.  These are PRINT
                    337:                   columns, not actual characters. */
                    338:                w->w_dotcol = find_pos(w->w_line, w->w_char);
                    339:                /* if the new dotcol is out of range, reselect
                    340:                   a horizontal window */
                    341:                if ((PhysScreen[i].s_offset == -1) ||
                    342:                    (w->w_dotcol < strt_col) ||
                    343:                    (w->w_dotcol >= end_col)) {
                    344:                        if (w->w_dotcol < ((CO - 2) - diff))
                    345:                                strt_col = 0;
                    346:                        else
                    347:                                strt_col = w->w_dotcol - (CO / 2);
                    348:                        if (ScrollAll == YES) {
                    349:                                if (w->w_LRscroll != strt_col)
                    350:                                        UpdModLine = YES;
                    351:                                w->w_LRscroll = strt_col;
                    352:                        }
                    353:                }
                    354:                w->w_dotline = i;
                    355:                w->w_dotcol += diff;
                    356:        }
                    357: 
                    358:        des_p = &DesiredScreen[upper];
                    359:        phys_p = &PhysScreen[upper];
                    360:        for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) {
                    361:                des_p->s_window = w;
                    362:                des_p->s_lp = lp;
                    363:                des_p->s_id = lp->l_dline & ~DIRTY;
                    364:                des_p->s_flags = isdirty(lp) ? L_MOD : 0;
                    365:                if (w->w_flags & W_NUMLINES)
                    366:                        des_p->s_vln = w->w_topnum + (i - upper);
                    367:                else
                    368:                        des_p->s_vln = 0;
                    369: 
                    370:                if (lp == w->w_line)
                    371:                        des_p->s_offset = strt_col;
                    372:                else
                    373:                        des_p->s_offset = w->w_LRscroll;
                    374:        }
                    375: 
                    376:        /* Is structure assignment faster than copy each field separately? */
                    377:        if (i < lower) {
                    378:                static const struct scrimage    dirty_plate = { 0, DIRTY, 0, 0, 0, 0 },
                    379:                                        clean_plate = { 0, 0, 0, 0, 0, 0 };
                    380: 
                    381:                for (; i < lower; i++, des_p++, phys_p++)
                    382:                        if (phys_p->s_id != 0)
                    383:                                *des_p = dirty_plate;
                    384:                        else
                    385:                                *des_p = clean_plate;
                    386:        }
                    387: 
                    388:        des_p->s_window = w;
                    389:        des_p->s_flags = 0;
                    390:        if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine)
                    391:                des_p->s_flags = MODELINE | DIRTY;
                    392: #ifdef MAC
                    393:        if (UpdModLine)
                    394:                Modechange = 1;
                    395:        if (w == curwind && w->w_control)
                    396:                SetScrollBar(w->w_control);
                    397: #endif
                    398: }
                    399: 
                    400: /* Write whatever is in mesgbuf (maybe we are Asking, or just printed
                    401:    a message).  Turns off the UpdateMesg line flag. */
                    402: 
                    403: void
                    404: DrawMesg(abortable)
                    405: int    abortable;
                    406: {
                    407: #ifndef MAC            /* same reason as in redisplay() */
                    408:        if (charp())
                    409:                return;
                    410: #endif
                    411:        i_set(ILI, 0);
                    412:        if (swrite(mesgbuf, NO, abortable)) {
                    413:                cl_eol();
                    414:                UpdMesg = 0;
                    415:        }
                    416:        flusho();
                    417: }
                    418: 
                    419: /* Goto the current position in the current window.  Presumably redisplay()
                    420:    has already been called, and curwind->{w_dotline,w_dotcol} have been set
                    421:    correctly. */
                    422: 
                    423: private void
                    424: GotoDot()
                    425: {
                    426:        if (InputPending)
                    427:                return;
                    428:        Placur(curwind->w_dotline, curwind->w_dotcol -
                    429:                                PhysScreen[curwind->w_dotline].s_offset);
                    430:        flusho();
                    431: }
                    432: 
                    433: private int
                    434: UntilEqual(start)
                    435: register int   start;
                    436: {
                    437:        register struct scrimage        *des_p = &DesiredScreen[start],
                    438:                                        *phys_p = &PhysScreen[start];
                    439: 
                    440:        while ((start < ILI) && (des_p->s_id != phys_p->s_id)) {
                    441:                des_p += 1;
                    442:                phys_p += 1;
                    443:                start += 1;
                    444:        }
                    445: 
                    446:        return start;
                    447: }
                    448: 
                    449: /* Calls the routine to do the physical changes, and changes PhysScreen to
                    450:    reflect those changes. */
                    451: 
                    452: private int
                    453: AddLines(at, num)
                    454: register int   at,
                    455:                num;
                    456: {
                    457:        register int    i;
                    458:        int     bottom = UntilEqual(at + num);
                    459: 
                    460:        if (num == 0 || num >= ((bottom - 1) - at))
                    461:                return NO;                              /* we did nothing */
                    462:        v_ins_line(num, at, bottom - 1);
                    463: 
                    464:        /* Now change PhysScreen to account for the physical change. */
                    465: 
                    466:        for (i = bottom - 1; i - num >= at; i--)
                    467:                PhysScreen[i] = PhysScreen[i - num];
                    468:        for (i = 0; i < num; i++)
                    469:                PhysScreen[at + i].s_id = 0;
                    470:        return YES;                                     /* we did something */
                    471: }
                    472: 
                    473: private int
                    474: DelLines(at, num)
                    475: register int   at,
                    476:                num;
                    477: {
                    478:        register int    i;
                    479:        int     bottom = UntilEqual(at + num);
                    480: 
                    481:        if (num == 0 || num >= ((bottom - 1) - at))
                    482:                return NO;
                    483:        v_del_line(num, at, bottom - 1);
                    484: 
                    485:        for (i = at; num + i < bottom; i++)
                    486:                PhysScreen[i] = PhysScreen[num + i];
                    487:        for (i = bottom - num; i < bottom; i++)
                    488:                PhysScreen[i].s_id = 0;
                    489:        return YES;
                    490: }
                    491: 
                    492: /* Update line linenum in window w.  Only set PhysScreen to DesiredScreen
                    493:    if the swrite or cl_eol works, that is nothing is interupted by
                    494:    characters typed. */
                    495: 
                    496: private void
                    497: UpdLine(linenum)
                    498: register int   linenum;
                    499: {
                    500:        register struct scrimage        *des_p = &DesiredScreen[linenum];
                    501:        register Window *w = des_p->s_window;
                    502: 
                    503:        i_set(linenum, 0);
                    504:        if (des_p->s_flags & MODELINE)
                    505:                ModeLine(w);
                    506:        else if (des_p->s_id) {
                    507:                des_p->s_lp->l_dline &= ~DIRTY;
                    508:                des_p->s_flags &= ~(DIRTY | L_MOD);
                    509: #ifdef ID_CHAR
                    510:                if (!UseIC && (w->w_flags & W_NUMLINES))
                    511: #else
                    512:                if (w->w_flags & W_NUMLINES)
                    513: #endif
                    514:                        (void) swrite(sprint("%6d  ", des_p->s_vln), NO, YES);
                    515: 
                    516: #ifdef ID_CHAR
                    517:                if (UseIC) {
                    518:                        char    outbuf[MAXCOLS],
                    519:                                *lptr;
                    520:                        int     fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0;
                    521: 
                    522:                        if (w->w_flags & W_NUMLINES)
                    523:                                swritef(outbuf, "%6d  ", des_p->s_vln);
                    524:                        lptr = lcontents(des_p->s_lp);
                    525:                        DeTab(des_p->s_offset, lptr, outbuf + fromcol,
                    526:                                (sizeof outbuf) - 1 - fromcol,
                    527:                                des_p->s_window->w_flags & W_VISSPACE);
                    528:                        if (IDchar(outbuf, linenum, 0))
                    529:                                PhysScreen[linenum] = *des_p;
                    530:                        else if (i_set(linenum, 0), swrite(outbuf, NO, YES))
                    531:                                do_cl_eol(linenum);
                    532:                        else
                    533:                                PhysScreen[linenum].s_id = -1;
                    534:                } else
                    535: #endif /* ID_CHAR */
                    536:                    if (BufSwrite(linenum))
                    537:                        do_cl_eol(linenum);
                    538:                else
                    539:                        PhysScreen[linenum].s_id = -1;
                    540:        } else if (PhysScreen[linenum].s_id)    /* not the same ... make sure */
                    541:                do_cl_eol(linenum);
                    542: }
                    543: 
                    544: private void
                    545: do_cl_eol(linenum)
                    546: register int   linenum;
                    547: {
                    548:        cl_eol();
                    549:        PhysScreen[linenum] = DesiredScreen[linenum];
                    550: }
                    551: 
                    552: #ifdef ID_CHAR
                    553: 
                    554: /* From here to the end of the file is code that tries to utilize the
                    555:    insert/delete character feature on some terminals.  It is very confusing
                    556:    and not so well written code, AND there is a lot of it.  You may want
                    557:    to use the space for something else. */
                    558: 
                    559: int    IN_INSmode = 0;
                    560: 
                    561: int    UseIC;
                    562: 
                    563: int    DClen,
                    564:        MDClen,
                    565:        IClen,
                    566:        MIClen,
                    567:        IMlen,
                    568:        CElen;
                    569: 
                    570: void
                    571: disp_opt_init()
                    572: {
                    573:        DClen = DC ? strlen(DC) : 0;
                    574:        MDClen = M_DC ? strlen(M_DC) : 9999;
                    575:        IClen = IC ? strlen(IC) : 0;
                    576:        MIClen = M_IC ? strlen(M_IC) : 9999;
                    577:        IMlen = IM ? strlen(IM) : 0;
                    578:        CElen = CE ? strlen(CE) : 0;
                    579: 
                    580:        UseIC = (IC || IM || M_IC);
                    581: }
                    582: 
                    583: void
                    584: INSmode(on)
                    585: int    on;
                    586: {
                    587:        if (on && !IN_INSmode) {
                    588:                putpad(IM, 1);
                    589:                IN_INSmode = YES;
                    590:        } else if (!on && IN_INSmode) {
                    591:                putpad(EI, 1);
                    592:                IN_INSmode = NO;
                    593:        }
                    594: }
                    595: 
                    596: private void
                    597: DeTab(s_offset, buf, outbuf, limit, visspace)
                    598: int    s_offset;
                    599: register char  *buf;
                    600: char   *outbuf;
                    601: size_t limit;
                    602: int    visspace;
                    603: {
                    604:        register char   *phys_p = outbuf,
                    605:                        c;
                    606:        register int    pos = 0;
                    607:        char            *limitp = &outbuf[limit];
                    608: 
                    609: #define OkayOut(ch)    { \
                    610:        if ((pos++ >= s_offset) && (phys_p < limitp)) \
                    611:                *phys_p++ = (ch); \
                    612: }
                    613: 
                    614:        while ((c = *buf++) != '\0') {
                    615:                if (c == '\t') {
                    616:                        int     nchars = (tabstop - (pos % tabstop));
                    617: 
                    618:                        if (visspace) {
                    619:                                OkayOut('>');
                    620:                                nchars -= 1;
                    621:                        }
                    622:                        while (--nchars >= 0)
                    623:                                OkayOut(' ');
                    624: 
                    625:                } else if (isctrl(c)) {
                    626:                        OkayOut('^');
                    627:                        OkayOut(c == 0177 ? '?' : c + '@');
                    628:                } else {
                    629:                        if (visspace && c == ' ')
                    630:                                c = '_';
                    631:                        OkayOut(c);
                    632:                }
                    633:                if (pos - s_offset >= CO) {
                    634:                        phys_p = &outbuf[CO - 1];
                    635:                        *phys_p++ = '!';
                    636:                        break;
                    637:                }
                    638:        }
                    639:        *phys_p = 0;
                    640: 
                    641: #undef OkayOut
                    642: }
                    643: 
                    644: /* ID character routines full of special cases and other fun stuff like that.
                    645:    It actually works though ...
                    646: 
                    647:        Returns Non-Zero if you are finished (no differences left). */
                    648: 
                    649: private int
                    650: IDchar(new, lineno, col)
                    651: register char  *new;
                    652: int    lineno,
                    653:        col;
                    654: {
                    655:        register int    i;
                    656:        int     j,
                    657:                oldlen,
                    658:                NumSaved;
                    659:        register struct screenline      *sline = &Screen[lineno];
                    660: 
                    661:        oldlen = sline->s_length - sline->s_line;
                    662: 
                    663:        for (i = col; i < oldlen && new[i] != 0; i++)
                    664:                if (sline->s_line[i] != new[i])
                    665:                        break;
                    666:        if (new[i] == 0 || i == oldlen)
                    667:                return (new[i] == 0 && i == oldlen);
                    668: 
                    669:        for (j = i + 1; j < oldlen && new[j]; j++) {
                    670:                if (new[j] == sline->s_line[i]) {
                    671:                        NumSaved = IDcomp(new + j, sline->s_line + i,
                    672:                                        (int)strlen(new)) + NumSimilar(new + i,
                    673:                                                sline->s_line + i, j - i);
                    674:                        if (OkayInsert(NumSaved, j - i)) {
                    675:                                InsChar(lineno, i, j - i, new);
                    676:                                return(IDchar(new, lineno, j));
                    677:                        }
                    678:                }
                    679:        }
                    680: 
                    681:        for (j = i + 1; j < oldlen && new[i]; j++) {
                    682:                if (new[i] == sline->s_line[j]) {
                    683:                        NumSaved = IDcomp(new + i, sline->s_line + j,
                    684:                                        oldlen - j);
                    685:                        if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) {
                    686:                                DelChar(lineno, i, j - i);
                    687:                                return(IDchar(new, lineno, i));
                    688:                        }
                    689:                }
                    690:        }
                    691:        return 0;
                    692: }
                    693: 
                    694: private int
                    695: NumSimilar(s, t, n)
                    696: register char  *s,
                    697:                *t;
                    698: int    n;
                    699: {
                    700:        register int    num = 0;
                    701: 
                    702:        while (n--)
                    703:                if (*s++ == *t++)
                    704:                        num += 1;
                    705:        return num;
                    706: }
                    707: 
                    708: private int
                    709: IDcomp(s, t, len)
                    710: register char  *s,
                    711:                *t;
                    712: int    len;
                    713: {
                    714:        register int    i;
                    715:        int     num = 0,
                    716:                nonspace = 0;
                    717:        char    c;
                    718: 
                    719:        for (i = 0; i < len; i++) {
                    720:                if ((c = *s++) != *t++)
                    721:                        break;
                    722:                if (c != ' ')
                    723:                        nonspace++;
                    724:                if (nonspace)
                    725:                        num += 1;
                    726:        }
                    727: 
                    728:        return num;
                    729: }
                    730: 
                    731: private int
                    732: OkayDelete(Saved, num, samelength)
                    733: int    Saved,
                    734:        num,
                    735:        samelength;
                    736: {
                    737:        /* If the old and the new are the same length, then we don't
                    738:         * have to clear to end of line.  We take that into consideration.
                    739:         */
                    740:        return ((Saved + (!samelength ? CElen : 0))
                    741:                > min(MDClen, DClen * num));
                    742: }
                    743: 
                    744: private int
                    745: OkayInsert(Saved, num)
                    746: int    Saved,
                    747:        num;
                    748: {
                    749:        register int    n = 0;
                    750: 
                    751:        if (IC)         /* Per character prefixes */
                    752:                n = min(num * IClen, MIClen);
                    753: 
                    754:        if (IM && !IN_INSmode) {
                    755:                /* Good terminal.  Fewer characters in this case */
                    756:                n += IMlen;
                    757:        }
                    758: 
                    759:        n += num;       /* The characters themselves */
                    760: 
                    761:        return Saved > n;
                    762: }
                    763: 
                    764: private void
                    765: DelChar(lineno, col, num)
                    766: int    lineno,
                    767:        col,
                    768:        num;
                    769: {
                    770:        register char   *from,
                    771:                        *to;
                    772:        register int    i;
                    773:        struct screenline *sp = (&Screen[lineno]);
                    774: 
                    775:        Placur(lineno, col);
                    776:        if (M_DC && num > 1) {
                    777:                putargpad(M_DC, num, num);
                    778:        } else {
                    779:                for (i = num; --i >= 0; )
                    780:                        putpad(DC, 1);
                    781:        }
                    782: 
                    783:        to = sp->s_line + col;
                    784:        from = to + num;
                    785: 
                    786:        byte_copy(from, to, (size_t) (sp->s_length - from + 1));
                    787:        clrline(sp->s_length - num, sp->s_length);
                    788:        sp->s_length -= num;
                    789: }
                    790: 
                    791: private void
                    792: InsChar(lineno, col, num, new)
                    793: int    lineno,
                    794:        col,
                    795:        num;
                    796: char   *new;
                    797: {
                    798:        register char   *sp1,
                    799:                        *sp2,   /* To push over the array. */
                    800:                        *sp3;   /* Last character to push over. */
                    801:        int     i;
                    802: 
                    803:        i_set(lineno, 0);
                    804:        sp2 = Curline->s_length + num;
                    805: 
                    806:        if (sp2 >= cursend) {
                    807:                i_set(lineno, CO - num - 1);
                    808:                cl_eol();
                    809:                sp2 = cursend - 1;
                    810:        }
                    811:        Curline->s_length = sp2;
                    812:        sp1 = sp2 - num;
                    813:        sp3 = Curline->s_line + col;
                    814: 
                    815:        while (sp1 >= sp3)
                    816:                *sp2-- = *sp1--;
                    817: 
                    818:        new += col;
                    819:        byte_copy(new, sp3, (size_t) num);
                    820:        /* The internal screen is correct, and now we have to do
                    821:           the physical stuff. */
                    822: 
                    823:        Placur(lineno, col);
                    824:        if (IM) {
                    825:                if (!IN_INSmode)
                    826:                        INSmode(1);
                    827:        } else if (M_IC && num > 1) {
                    828:                putargpad(M_IC, num, num);
                    829:        } else if (IC) {
                    830:                for (i = 0; i < num; i++)
                    831:                        putpad(IC, 1);
                    832:        }
                    833:        for (i = 0; i < num; i++) {
                    834:                jputchar(new[i]);
                    835:                if (IN_INSmode)
                    836:                        putpad(IP, 1);
                    837:        }
                    838:        CapCol += num;
                    839: }
                    840: 
                    841: #endif /* ID_CHAR */
                    842: 
                    843: #ifdef UNIX            /* obviously ... no mail today if not Unix*/
                    844: 
                    845: /* chkmail() returns nonzero if there is new mail since the
                    846:    last time we checked. */
                    847: 
                    848: char   Mailbox[FILESIZE];      /* initialized in main */
                    849: int    MailInt = 60;           /* check no more often than 60 seconds */
                    850: #ifdef BIFF
                    851: int    BiffChk = NO;           /* whether to turn off biff while in JOVE */
                    852: #endif
                    853: 
                    854: int
                    855: chkmail(force)
                    856: int    force;
                    857: {
                    858:        time_t  now;
                    859:        static int      state = NO;     /* assume unknown */
                    860:        static time_t   last_chk = 0,
                    861:                        mbox_time = 0;
                    862:        struct stat     stbuf;
                    863: 
                    864:        if (MailInt == 0)
                    865:                return NO;
                    866:        time(&now);
                    867:        if ((force == NO) && (now < last_chk + MailInt))
                    868:                return state;
                    869:        last_chk = now;
                    870:        if (stat(Mailbox, &stbuf) < 0) {
                    871:                state = NO;             /* no mail */
                    872:                return NO;
                    873:        }
                    874:        if (((stbuf.st_atime > stbuf.st_mtime) &&
                    875:             (stbuf.st_atime > mbox_time)) ||
                    876:            (stbuf.st_size == 0)) {
                    877:                mbox_time = stbuf.st_atime;
                    878:                state = NO;
                    879:        } else if (stbuf.st_mtime > mbox_time) {
                    880:                if (mbox_time > 0)
                    881:                        dobell(2);              /* announce the change */
                    882:                mbox_time = stbuf.st_mtime;
                    883:                state = YES;
                    884:        }
                    885:        return state;
                    886: }
                    887: 
                    888: #endif /* UNIX */
                    889: 
                    890: /* Print the mode line. */
                    891: 
                    892: private char   *mode_p,
                    893:                *mend_p;
                    894: int    BriteMode = 1;          /* modeline should standout */
                    895: 
                    896: private void
                    897: mode_app(str)
                    898: register const char    *str;
                    899: {
                    900:        while ((mode_p < mend_p) && (*mode_p++ = *str++)!='\0')
                    901:                ;
                    902:        mode_p -= 1;    /* back over the null */
                    903: }
                    904: 
                    905: char   ModeFmt[120] = "%3c %w %[%sJOVE (%M)   Buffer: %b  \"%f\" %]%s%m*- %((%t)%s%)%e";
                    906: 
                    907: private void
                    908: ModeLine(w)
                    909: register Window        *w;
                    910: {
                    911:        int     n,
                    912:                ign_some = NO,
                    913:                glue = 0;
                    914:        char    line[MAXCOLS],
                    915:                *fmt = ModeFmt,
                    916:                fillc,
                    917:                c;
                    918:        register Buffer *thisbuf = w->w_bufp;
                    919:        register Buffer *bp;
                    920: 
                    921:        mode_p = line;
                    922:        mend_p = &line[(sizeof line) - 1];
                    923: 
                    924: #ifdef IBMPC
                    925:        /* very subtle - don't mess up attributes too much */
                    926:        fillc = '-';
                    927: #else /* !IBMPC */
                    928: #  ifdef MAC
                    929:        fillc = '_';    /* looks better on a Mac */
                    930: #  else /* !MAC */
                    931:        if (SO == 0)
                    932:                BriteMode = 0;
                    933:        fillc = BriteMode ? ' ' : '-';
                    934: #  endif /* !MAC */
                    935: #endif /* !IBMPC */
                    936: 
                    937:        while ((c = *fmt++)!='\0' && mode_p<mend_p) {
                    938:                if (c != '%') {
                    939:                        if (c == '\\')
                    940:                                if ((c = *fmt++) == '\0')
                    941:                                        break;
                    942:                        if (!ign_some)
                    943:                                *mode_p++ = c;
                    944:                        continue;
                    945:                }
                    946:                if ((c = *fmt++) == '\0')       /* char after the '%' */
                    947:                        break;
                    948:                if (ign_some && c != ')')
                    949:                        continue;
                    950:                n = 1;
                    951:                if (c >= '0' && c <= '9') {
                    952:                        n = 0;
                    953:                        while (c >= '0' && c <= '9') {
                    954:                                n = n * 10 + (c - '0');
                    955:                                c = *fmt++;
                    956:                        }
                    957:                        if (c == '\0')
                    958:                                break;
                    959:                }
                    960:                switch (c) {
                    961:                case '(':
                    962:                        if (w->w_next != fwind) /* Not bottom window. */
                    963:                                ign_some = YES;
                    964:                        break;
                    965: 
                    966:                case ')':
                    967:                        ign_some = NO;
                    968:                        break;
                    969: 
                    970:                case '[':
                    971:                case ']':
                    972:                        for (n=RecDepth; n>0 && mode_p<mend_p; n--)
                    973:                                *mode_p++ = c;
                    974:                        break;
                    975: 
                    976: #ifdef UNIX
                    977:                case 'C':       /* check mail here */
                    978:                        if (chkmail(NO) == YES)
                    979:                                mode_app("[New mail]");
                    980:                        break;
                    981: 
                    982: #endif /* UNIX */
                    983: 
                    984:                case 'M':
                    985:                    {
                    986:                        static const char       *const mmodes[] = {
                    987:                                "Fundamental ",
                    988:                                "Text ",
                    989:                                "C ",
                    990: #ifdef LISP
                    991:                                "Lisp ",
                    992: #endif
                    993:                                0
                    994:                        };
                    995: 
                    996:                        mode_app(mmodes[thisbuf->b_major]);
                    997: 
                    998:                        if (BufMinorMode(thisbuf, Fill))
                    999:                                mode_app("Fill ");
                   1000:                        if (BufMinorMode(thisbuf, Abbrev))
                   1001:                                mode_app("Abbrev ");
                   1002:                        if (BufMinorMode(thisbuf, OverWrite))
                   1003:                                mode_app("OvrWt ");
                   1004:                        if (BufMinorMode(thisbuf, Indent))
                   1005:                                mode_app("AI ");
                   1006:                        if (BufMinorMode(thisbuf, ReadOnly))
                   1007:                                mode_app("RO ");
                   1008:                        if (InMacDefine)
                   1009:                                mode_app("Def ");
                   1010:                        mode_p -= 1;    /* Back over the extra space. */
                   1011:                        break;
                   1012:                    }
                   1013: 
                   1014:                case 'c':
                   1015:                        while (--n>=0 && mode_p<mend_p)
                   1016:                                *mode_p++ = fillc;
                   1017:                        break;
                   1018: 
                   1019:                case 'd':       /* print working directory */
                   1020:                        mode_app(pr_name(pwd(), YES));
                   1021:                        break;
                   1022: 
                   1023:                case 'e':       /* stretchable glue */
                   1024:                        *mode_p++ = '\0';       /* glue marker */
                   1025:                        glue++;
                   1026:                        break;
                   1027: 
                   1028:                case 'b':
                   1029:                        mode_app(thisbuf->b_name);
                   1030:                        break;
                   1031: 
                   1032:                case 'f':
                   1033:                case 'F':
                   1034:                        if (thisbuf->b_fname == 0)
                   1035:                                mode_app("[No file]");
                   1036:                        else {
                   1037:                                if (c == 'f')
                   1038:                                        mode_app(pr_name(thisbuf->b_fname, YES));
                   1039:                                else
                   1040:                                        mode_app(basename(thisbuf->b_fname));
                   1041:                        }
                   1042:                        break;
                   1043: 
                   1044: #ifdef LOAD_AV
                   1045:                case 'l':
                   1046:                    {
                   1047:                        double  theavg;
                   1048:                        char    minibuf[10];
                   1049: 
                   1050:                        get_la(&theavg);
                   1051:                        theavg += .005; /* round to nearest .01 */
                   1052:                        swritef(minibuf, "%d.%02d",
                   1053:                               (int) theavg,
                   1054:                               (int)((theavg - (int) theavg) * 100));
                   1055:                        mode_app(minibuf);
                   1056:                        break;
                   1057:                    }
                   1058: #endif
                   1059: 
                   1060:                case 'm':
                   1061:                    {
                   1062:                        char    yea = (*fmt == '\0') ? '*' : *fmt++;
                   1063:                        char    nay = (*fmt == '\0') ? ' ' : *fmt++;
                   1064: 
                   1065:                        *mode_p++ = IsModified(w->w_bufp) ? yea : nay;
                   1066:                        break;
                   1067:                    }
                   1068: 
                   1069:                case 'n':
                   1070:                    {
                   1071:                        char    tmp[16];
                   1072:                        for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++)
                   1073:                                if (bp == thisbuf)
                   1074:                                        break;
                   1075: 
                   1076:                        swritef(tmp, "%d", n);
                   1077:                        mode_app(tmp);
                   1078:                        break;
                   1079:                    }
                   1080: 
                   1081: #ifdef IPROCS
                   1082:                case 'p':
                   1083:                        if (thisbuf->b_type == B_PROCESS) {
                   1084:                                char    tmp[40];
                   1085:                                Process *p = thisbuf->b_process;
                   1086: 
                   1087:                                swritef(tmp, "(%s%s)",
                   1088:                                        ((p == 0 || p->p_dbx_mode == NO)
                   1089:                                         ? "" : "DBX "),
                   1090:                                        ((p == 0) ? "No process" :
                   1091:                                         pstate(p)));
                   1092:                                mode_app(tmp);
                   1093:                        }
                   1094:                        break;
                   1095: #endif
                   1096: 
                   1097:                case 's':
                   1098:                        if (mode_p[-1] != ' ')
                   1099:                                *mode_p++ = ' ';
                   1100:                        break;
                   1101: 
                   1102:                case 't':
                   1103:                    {
                   1104:                        char    timestr[12];
                   1105: 
                   1106:                        mode_app(get_time((time_t *) 0, timestr, 11, 16));
                   1107:                        break;
                   1108:                    }
                   1109: 
                   1110:                case 'w':
                   1111:                        if (w->w_LRscroll > 0)
                   1112:                                mode_app(">");
                   1113:                        break;
                   1114:                }
                   1115:        }
                   1116: 
                   1117:        /* Glue (Knuth's term) is a field that expands to fill
                   1118:         * any leftover space.  Multiple glue fields compete
                   1119:         * on an equal basis.  This is a generalization of a
                   1120:         * mechanism to allow centring and right-justification.
                   1121:         * The original meaning of %e (fill the rest of the
                   1122:         * line) has also been generalized.  %e can now
                   1123:         * meaningfully be used 0 or more times.
                   1124:         */
                   1125: 
                   1126:        if  (glue) {
                   1127:                /* 2 space pad plus padding for magic cookies */
                   1128:                register char   *to = &line[CO - 2 - (2 * SG)],
                   1129:                                *from = mode_p;
                   1130: 
                   1131:                if (to < from)
                   1132:                        to = from;
                   1133:                mode_p = to;
                   1134:                while (from != line) {
                   1135:                        if ((*--to = *--from) == '\0') {
                   1136:                                register int    portion = (to-from) / glue;
                   1137: 
                   1138:                                glue--;
                   1139:                                *to = fillc;
                   1140:                                while (--portion >= 0)
                   1141:                                        *--to = fillc;
                   1142:                        }
                   1143:                }
                   1144:        }
                   1145: 
                   1146:        *mode_p = 0;
                   1147: 
                   1148:        /* Highlight mode line. */
                   1149:        if (BriteMode) {
                   1150: #ifdef ID_CHAR
                   1151:                if (IN_INSmode)
                   1152:                        INSmode(0);
                   1153: #endif
                   1154:                SO_on();
                   1155:        }
                   1156:        if (swrite(line, BriteMode, YES))
                   1157:                do_cl_eol(i_line);
                   1158:        else
                   1159:                UpdModLine = 1;
                   1160:        if (BriteMode)
                   1161:                SO_off();
                   1162: }
                   1163: 
                   1164: private void
                   1165: v_clear(line1, line2)
                   1166: register int   line1;
                   1167: int    line2;
                   1168: {
                   1169:        register struct scrimage        *phys_p, *des_p;
                   1170: 
                   1171:        phys_p = &PhysScreen[line1];
                   1172:        des_p = &DesiredScreen[line1];
                   1173: 
                   1174:        while (line1 <= line2) {
                   1175:                i_set(line1, 0);
                   1176:                cl_eol();
                   1177:                phys_p->s_id = des_p->s_id = 0;
                   1178:                phys_p += 1;
                   1179:                des_p += 1;
                   1180:                line1 += 1;
                   1181:        }
                   1182: }
                   1183: 
                   1184: /* This tries to place the current line of the current window in the
                   1185:    center of the window, OR to place it at the arg'th line of the window.
                   1186:    This also causes the horizontal position of the line to be centered,
                   1187:    if the line needs scrolling, or moved all the way back to the left,
                   1188:    if that's possible. */
                   1189: void
                   1190: RedrawDisplay()
                   1191: {
                   1192:        int     line;
                   1193:        Line    *newtop = prev_line((curwind->w_line = curline), is_an_arg() ?
                   1194:                                arg_value() : HALF(curwind));
                   1195: 
                   1196:        if ((line = in_window(curwind, curwind->w_line)) != -1)
                   1197:                PhysScreen[line].s_offset = -1;
                   1198:        if (newtop == curwind->w_top)
                   1199:                v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind));
                   1200:        else
                   1201:                SetTop(curwind, newtop);
                   1202: }
                   1203: 
                   1204: void
                   1205: ClAndRedraw()
                   1206: {
                   1207:        cl_scr(YES);
                   1208: }
                   1209: 
                   1210: void
                   1211: NextPage()
                   1212: {
                   1213:        Line    *newline;
                   1214: 
                   1215:        if (Asking)
                   1216:                return;
                   1217:        if (arg_value() < 0) {
                   1218:                negate_arg_value();
                   1219:                PrevPage();
                   1220:                return;
                   1221:        }
                   1222:        if (arg_type() == YES)
                   1223:                UpScroll();
                   1224:        else {
                   1225:                if (in_window(curwind, curwind->w_bufp->b_last) != -1) {
                   1226:                        rbell();
                   1227:                        return;
                   1228:                }
                   1229:                newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1));
                   1230:                SetTop(curwind, curwind->w_line = newline);
                   1231:                if (curwind->w_bufp == curbuf)
                   1232:                        SetLine(newline);
                   1233:        }
                   1234: }
                   1235: 
                   1236: #ifdef MSDOS           /* kg */
                   1237: 
                   1238: void
                   1239: PageScrollUp()
                   1240: {
                   1241:        int i, n;
                   1242: 
                   1243:     n = max(1, SIZE(curwind) - 1);
                   1244:        for (i=0; i<n; i++) {
                   1245:            UpScroll();
                   1246:            redisplay();
                   1247:        }
                   1248: }
                   1249: 
                   1250: void
                   1251: PageScrollDown()
                   1252: {
                   1253:        int i, n;
                   1254: 
                   1255:        n = max(1, SIZE(curwind) - 1);
                   1256:        for (i=0; i<n; i++) {
                   1257:            DownScroll();
                   1258:            redisplay();
                   1259:        }
                   1260: }
                   1261: #endif /* MSDOS */
                   1262: 
                   1263: void
                   1264: PrevPage()
                   1265: {
                   1266:        Line    *newline;
                   1267: 
                   1268:        if (Asking)
                   1269:                return;
                   1270:        if (arg_value() < 0) {
                   1271:                negate_arg_value();
                   1272:                NextPage();
                   1273:                return;
                   1274:        }
                   1275:        if (arg_type() == YES)
                   1276:                DownScroll();
                   1277:        else {
                   1278:                newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1));
                   1279:                SetTop(curwind, curwind->w_line = newline);
                   1280:                if (curwind->w_bufp == curbuf)
                   1281:                        SetLine(newline);
                   1282:        }
                   1283: }
                   1284: 
                   1285: void
                   1286: UpScroll()
                   1287: {
                   1288:        SetTop(curwind, next_line(curwind->w_top, arg_value()));
                   1289:        if ((curwind->w_bufp == curbuf) &&
                   1290:            (in_window(curwind, curline) == -1))
                   1291:                SetLine(curwind->w_top);
                   1292: }
                   1293: 
                   1294: void
                   1295: DownScroll()
                   1296: {
                   1297:        SetTop(curwind, prev_line(curwind->w_top, arg_value()));
                   1298:        if ((curwind->w_bufp == curbuf) &&
                   1299:            (in_window(curwind, curline) == -1))
                   1300:                SetLine(curwind->w_top);
                   1301: }
                   1302: 
                   1303: int    VisBell = NO;
                   1304: 
                   1305: void
                   1306: rbell()
                   1307: {
                   1308:        RingBell = YES;
                   1309: }
                   1310: 
                   1311: /* Message prints the null terminated string onto the bottom line of the
                   1312:    terminal. */
                   1313: 
                   1314: void
                   1315: message(str)
                   1316: char   *str;
                   1317: {
                   1318:        if (InJoverc)
                   1319:                return;
                   1320:        UpdMesg = YES;
                   1321:        errormsg = NO;
                   1322:        if (str != mesgbuf)
                   1323:                null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1);
                   1324: }
                   1325: 
                   1326: /* End of Window */
                   1327: 
                   1328: void
                   1329: Eow()
                   1330: {
                   1331:        if (Asking)
                   1332:                return;
                   1333:        SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 -
                   1334:                        min(SIZE(curwind) - 1, arg_value() - 1)));
                   1335:        if (!is_an_arg())
                   1336:                Eol();
                   1337: }
                   1338: 
                   1339: /* Beginning of Window */
                   1340: 
                   1341: void
                   1342: Bow()
                   1343: {
                   1344:        if (Asking)
                   1345:                return;
                   1346:        SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, arg_value() - 1)));
                   1347: }
                   1348: 
                   1349: private int    LineNo,
                   1350:                last_col,
                   1351:                DoAutoNL;
                   1352: private Window *old_wind;      /* save the window we were in BEFORE
                   1353:                                   before we were called, if UseBuffers
                   1354:                                   is nonzero */
                   1355: 
                   1356: int    UseBuffers = FALSE;
                   1357: int    TOabort = 0;
                   1358: 
                   1359: /* This initializes the typeout.  If send-typeout-to-buffers is set
                   1360:    the buffer NAME is created (emptied if it already exists) and output
                   1361:    goes to the buffer.  Otherwise output is drawn on the screen and
                   1362:    erased by TOstop() */
                   1363: 
                   1364: void
                   1365: TOstart(name, auto_newline)
                   1366: char   *name;
                   1367: int    auto_newline;
                   1368: {
                   1369:        if (UseBuffers) {
                   1370:                old_wind = curwind;
                   1371:                pop_wind(name, YES, B_SCRATCH);
                   1372:        } else
                   1373:                DisabledRedisplay = YES;
                   1374:        TOabort = LineNo = last_col = 0;
                   1375:        DoAutoNL = auto_newline;
                   1376: }
                   1377: 
                   1378: #ifdef STDARGS
                   1379:        void
                   1380: Typeout(char *fmt, ...)
                   1381: #else
                   1382:        /*VARARGS1*/ void
                   1383: Typeout(fmt, va_alist)
                   1384:        char    *fmt;
                   1385:        va_dcl
                   1386: #endif
                   1387: {
                   1388:        if (TOabort)
                   1389:                return;
                   1390: 
                   1391:        if (!UseBuffers && (LineNo == ILI - 1)) {
                   1392:                register int    c;
                   1393: 
                   1394:                LineNo = 0;
                   1395:                last_col = 0;
                   1396:                f_mess("--more--");
                   1397:                if ((c = jgetchar()) != ' ') {
                   1398:                        TOabort = YES;
                   1399:                        if (c != AbortChar && c != RUBOUT)
                   1400:                                Ungetc(c);
                   1401:                        f_mess(NullStr);
                   1402:                        return;
                   1403:                }
                   1404:                f_mess(NullStr);
                   1405:        }
                   1406: 
                   1407:        if (fmt) {
                   1408:                char    string[132];
                   1409:                va_list ap;
                   1410: 
                   1411:                va_init(ap, fmt);
                   1412:                format(string, sizeof string, fmt, ap);
                   1413:                va_end(ap);
                   1414:                if (UseBuffers)
                   1415:                        ins_str(string, NO);
                   1416:                else {
                   1417:                        i_set(LineNo, last_col);
                   1418:                        (void) swrite(string, NO, YES);
                   1419:                        last_col = i_col;
                   1420:                }
                   1421:        }
                   1422:        if (!UseBuffers) {
                   1423:                PhysScreen[LineNo].s_id = -1;
                   1424:                if (fmt == 0 || DoAutoNL == YES) {
                   1425:                        cl_eol();
                   1426:                        flusho();
                   1427:                        LineNo += 1;
                   1428:                        last_col = 0;
                   1429:                }
                   1430:        } else if (fmt == 0 || DoAutoNL != 0)
                   1431:                ins_str("\n", NO);
                   1432: }
                   1433: 
                   1434: void
                   1435: TOstop()
                   1436: {
                   1437:        int     c;
                   1438: 
                   1439:        if (UseBuffers) {
                   1440:                ToFirst();
                   1441:                SetWind(old_wind);
                   1442:        } else {
                   1443:                if (TOabort) {
                   1444:                        DisabledRedisplay = NO;
                   1445:                        return;
                   1446:                }
                   1447:                if (last_col != 0)
                   1448:                        Typeout((char *) 0);
                   1449:                Typeout("----------");
                   1450:                cl_eol();
                   1451:                flusho();
                   1452:                c = jgetchar();
                   1453:                if (c != ' ')
                   1454:                        Ungetc(c);
                   1455:                DisabledRedisplay = NO;
                   1456:        }
                   1457: }

unix.superglobalmegacorp.com

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