Annotation of 43BSDTahoe/new/B/src/bed/scrn.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
                      2: static char rcsid[] = "$Header: scrn.c,v 2.5 85/08/22 16:07:10 timo Exp $";
                      3: 
                      4: /*
                      5:  * B editor -- Screen management package, higher level routines.
                      6:  */
                      7: 
                      8: #include "b.h"
                      9: #include "erro.h"
                     10: #include "bobj.h"
                     11: #include "node.h"
                     12: #include "supr.h"
                     13: #include "gram.h"
                     14: #include "cell.h"
                     15: 
                     16: 
                     17: extern bool dflag;
                     18: 
                     19: cell *gettop();
                     20: extern int focy;
                     21: extern int focx;
                     22: 
                     23: Visible int winstart;
                     24: 
                     25: Visible int winheight;
                     26: Visible int indent;
                     27: Visible int llength;
                     28: 
                     29: Visible bool noscroll;
                     30: Visible bool nosense;
                     31: 
                     32: Hidden cell *tops;
                     33: 
                     34: 
                     35: /*
                     36:  * Actual screen update.
                     37:  */
                     38: 
                     39: Visible Procedure
                     40: actupdate(copybuffer, recording, lasttime)
                     41:        value copybuffer;
                     42:        bool recording;
                     43:        bool lasttime; /* Yes if called from final screen update */
                     44: {
                     45:        register cell *p;
                     46:        cell *top = tops;
                     47:        register int diff;
                     48:        register int curlno;
                     49:        register int delcnt = 0; /* Lines deleted during the process. */
                     50:                /* Used as offset for lines that are on the screen. */
                     51:        int totlines = 0;
                     52:        int topline = 0;
                     53:        int scrlines = 0;
                     54: 
                     55:        if (winstart > 0)
                     56:                growwin();
                     57:        if (winstart <= 0) {
                     58:                top = gettop(tops);
                     59:                for (p = tops; p && p != top; p = p->c_link)
                     60:                        ++topline;
                     61:                totlines = topline;
                     62:        }
                     63:        startactupdate(lasttime);
                     64:        focy = Nowhere;
                     65:        for (p = top, curlno = winstart; p && curlno < winheight;
                     66:                curlno += Space(p), p = p->c_link) {
                     67:                ++scrlines;
                     68:                if (lasttime) {
                     69:                        p->c_newfocus = No;
                     70:                        p->c_newvhole = 0;
                     71:                }
                     72:                if (p->c_onscreen != Nowhere && Space(p) == Oldspace(p)) {
                     73:                        /* Old comrade */
                     74:                        diff = p->c_onscreen - (curlno+delcnt);
                     75:                        /* diff can't be negative due to 'makeroom' below! */
                     76:                        if (diff > 0) { /* Get him here */
                     77:                                trmscrollup(curlno, winheight, diff);
                     78:                                delcnt += diff;
                     79:                        }
                     80:                        if (p->c_oldfocus || p->c_newfocus
                     81:                                || p->c_oldindent != p->c_newindent
                     82:                                || p->c_onscreen + Space(p) >= winheight) {
                     83:                                delcnt = make2room(p, curlno, delcnt);
                     84:                                outline(p, curlno);
                     85:                        }
                     86:                }
                     87:                else { /* New guy, make him toe the line */
                     88:                        delcnt = makeroom(p, curlno, delcnt);
                     89:                        delcnt = make2room(p, curlno, delcnt);
                     90:                        outline(p, curlno);
                     91:                }
                     92:                p->c_onscreen = curlno;
                     93:                p->c_oldindent = p->c_newindent;
                     94:                p->c_oldvhole = p->c_newvhole;
                     95:                p->c_oldfocus = p->c_newfocus;
                     96:        }
                     97:        totlines += scrlines;
                     98:        for (; p; p = p->c_link) { /* Count rest and remove old memories */
                     99:                ++totlines;
                    100:                /* This code should never find any garbage?! */
                    101: #ifndef NDEBUG
                    102:                if (p->c_onscreen != Nowhere)
                    103:                        debug("[Garbage removed from screen list]");
                    104: #endif NDEBUG
                    105:                p->c_onscreen = Nowhere;
                    106:        }
                    107:        trmscrollup(curlno, winheight, -delcnt);
                    108:        curlno += delcnt;
                    109:        if (curlno < winheight) { /* Clear lines beyond end of unit */
                    110:                trmputdata(curlno, winheight-1, 0, "");
                    111:                scrlines += winheight-curlno;
                    112:        }
                    113:        if (!lasttime) {
                    114:                stsline(totlines, topline, scrlines, copybuffer, recording);
                    115:                if (focy != Nowhere)
                    116:                        trmsync(focy, focx);
                    117:                else
                    118:                        trmsync(winheight, 0);
                    119:        }
                    120:        endactupdate();
                    121: }
                    122: 
                    123: 
                    124: /*
                    125:  * Grow the window if not maximum size.
                    126:  */
                    127: 
                    128: Hidden Procedure
                    129: growwin()
                    130: {
                    131:        register int winsize;
                    132:        register int growth;
                    133:        register cell *p;
                    134: 
                    135:        winsize = 0;
                    136:        for (p = tops; p; p = p->c_link)
                    137:                winsize += Space(p);
                    138:        if (winsize <= winheight - winstart)
                    139:                return; /* No need to grow */
                    140:        if (winsize > winheight)
                    141:                winsize = winheight; /* Limit size to maximum available */
                    142: 
                    143:        growth = winsize - (winheight - winstart);
                    144:        trmscrollup(0, winheight - (winstart!=winheight), growth);
                    145:        winstart -= growth;
                    146:        for (p = tops; p; p = p->c_link) {
                    147:                if (p->c_onscreen != Nowhere)
                    148:                        p->c_onscreen -= growth;
                    149:        }
                    150: }
                    151: 
                    152: 
                    153: /*
                    154:  * Make room for possible insertions.
                    155:  * (If a line is inserted, it may be necessary to delete lines
                    156:  * further on the screen.)
                    157:  */
                    158: 
                    159: Hidden Procedure
                    160: makeroom(p, curlno, delcnt)
                    161:        register cell *p;
                    162:        register int curlno;
                    163:        register int delcnt;
                    164: {
                    165:        register int here = 0;
                    166:        register int need = Space(p);
                    167:        register int amiss;
                    168:        int avail;
                    169:        int diff;
                    170: 
                    171:        Assert(p);
                    172:        do {
                    173:                p = p->c_link;
                    174:                if (!p)
                    175:                        return delcnt;
                    176:        } while (p->c_onscreen == Nowhere);
                    177:        here = p->c_onscreen - delcnt;
                    178:        avail = here - curlno;
                    179:        amiss = need - avail;
                    180: #ifndef NDEBUG
                    181:        if (dflag)
                    182:                debug("[makeroom: curlno=%d, delcnt=%d, here=%d, avail=%d, amiss=%d]",
                    183:                        curlno, delcnt, here, avail, amiss);
                    184: #endif NDEBUG
                    185:        if (amiss <= 0)
                    186:                return delcnt;
                    187:        if (amiss > delcnt) {
                    188:                for (; p; p = p->c_link) {
                    189:                        if (p->c_onscreen != Nowhere) {
                    190:                                diff = amiss-delcnt;
                    191:                                if (p->c_onscreen - delcnt - here < diff)
                    192:                                        diff = p->c_onscreen - delcnt - here;
                    193:                                if (diff > 0) {
                    194:                                        trmscrollup(here, winheight, diff);
                    195:                                        delcnt += diff;
                    196:                                }
                    197:                                p->c_onscreen += -delcnt + amiss;
                    198:                                here = p->c_onscreen - amiss;
                    199:                                if (p->c_onscreen >= winheight)
                    200:                                        p->c_onscreen = Nowhere;
                    201:                        }
                    202:                        here += Space(p);
                    203:                }
                    204:                /* Now for all p encountered whose p->c_onscreen != Nowhere,
                    205:                /* p->c_onscreen - amiss is its actual position. */
                    206:                if (amiss > delcnt) {
                    207:                        trmscrollup(winheight - amiss, winheight, amiss-delcnt);
                    208:                        delcnt = amiss;
                    209:                }
                    210:        }
                    211:        /* Now amiss <= delcnt */
                    212:        trmscrollup(curlno + avail, winheight, -amiss);
                    213:        return delcnt - amiss;
                    214: }
                    215: 
                    216: 
                    217: /*
                    218:  * Addition to makeroom - make sure the status line is not overwritten.
                    219:  * Returns new delcnt, like makeroom does.
                    220:  */
                    221: 
                    222: Hidden int
                    223: make2room(p, curlno, delcnt)
                    224:        cell *p;
                    225:        int curlno;
                    226:        int delcnt;
                    227: {
                    228:        int nextline = curlno + Space(p);
                    229:        int sline = winheight - delcnt;
                    230:        int diff;
                    231: 
                    232:        if (sline < curlno) {
                    233: #ifndef NDEBUG
                    234:                debug("[Status line overwritten]");
                    235: #endif NDEBUG
                    236:                return delcnt;
                    237:        }
                    238:        if (nextline > winheight)
                    239:                nextline = winheight;
                    240:        diff = nextline - sline;
                    241:        if (diff > 0) {
                    242:                trmscrollup(sline, winheight, -diff);
                    243:                delcnt -= diff;
                    244:        }
                    245:        return delcnt;
                    246:                
                    247: }
                    248: 
                    249: 
                    250: /*
                    251:  * Routine called for every change in the screen.
                    252:  */
                    253: 
                    254: Visible Procedure
                    255: virtupdate(oldep, newep, highest)
                    256:        environ *oldep;
                    257:        environ *newep;
                    258:        int highest;
                    259: {
                    260:        environ old;
                    261:        environ new;
                    262:        register int oldlno;
                    263:        register int newlno;
                    264:        register int oldlcnt;
                    265:        register int newlcnt;
                    266:        register int i;
                    267: 
                    268:        if (!oldep) {
                    269:                highest = 1;
                    270:                trmputdata(winstart, winheight, indent, "");
                    271:                discard(tops);
                    272:                tops = Cnil;
                    273:                Ecopy(*newep, old);
                    274:        }
                    275:        else {
                    276:                Ecopy(*oldep, old);
                    277:        }
                    278:        Ecopy(*newep, new);
                    279: 
                    280:        savefocus(&new);
                    281: 
                    282:        oldlcnt = fixlevels(&old, &new, highest);
                    283:        newlcnt = -width(tree(new.focus));
                    284:        if (newlcnt < 0)
                    285:                newlcnt = 0;
                    286:        i = -width(tree(old.focus));
                    287:        if (i < 0)
                    288:                i = 0;
                    289:        newlcnt -= i - oldlcnt;
                    290:                /* Offset newlcnt as much as oldcnt is offset */
                    291:        
                    292:        oldlno = Ycoord(old.focus);
                    293:        newlno = Ycoord(new.focus);
                    294:        if (!atlinestart(&old))
                    295:                ++oldlcnt;
                    296:        else
                    297:                ++oldlno;
                    298:        if (!atlinestart(&new))
                    299:                ++newlcnt;
                    300:        else
                    301:                ++newlno;
                    302:        Assert(oldlno == newlno);
                    303: 
                    304:        tops = replist(tops, build(new.focus, newlcnt), oldlno, oldlcnt);
                    305: 
                    306:        setfocus(tops); /* Incorporate the information saved by savefocus */
                    307: 
                    308:        Erelease(old);
                    309:        Erelease(new);
                    310: }
                    311: 
                    312: 
                    313: Hidden bool
                    314: atlinestart(ep)
                    315:        environ *ep;
                    316: {
                    317:        register string repr = noderepr(tree(ep->focus))[0];
                    318: 
                    319:        return Fw_negative(repr);
                    320: }
                    321: 
                    322: 
                    323: /*
                    324:  * Make the two levels the same, and make sure they both are line starters
                    325:  * if at all possible.  Return the OLD number of lines to be replaced.
                    326:  * (0 if the whole unit has no linefeeds.)
                    327:  */
                    328: 
                    329: Hidden int
                    330: fixlevels(oldep, newep, highest)
                    331:        register environ *oldep;
                    332:        register environ *newep;
                    333:        register int highest;
                    334: {
                    335:        register int oldpl = pathlength(oldep->focus);
                    336:        register int newpl = pathlength(newep->focus);
                    337:        register bool intraline = No;
                    338:        register int w;
                    339: 
                    340:        if (oldpl < highest)
                    341:                highest = oldpl;
                    342:        if (newpl < highest)
                    343:                highest = newpl;
                    344:        while (oldpl > highest) {
                    345:                up(&oldep->focus) || Abort();
                    346:                --oldpl;
                    347:        }
                    348:        while (newpl > highest) {
                    349:                up(&newep->focus) || Abort();
                    350:                --newpl;
                    351:        }
                    352:        if (Ycoord(newep->focus) != Ycoord(oldep->focus) ||
                    353:                Level(newep->focus) != Level(newep->focus)) {
                    354:                /* Inconsistency found.  */
                    355:                Assert(highest > 1); /* Inconsistency at top level. Stop. */
                    356:                return fixlevels(oldep, newep, 1); /* Try to recover. */
                    357:        }
                    358:        intraline = width(tree(oldep->focus)) >= 0
                    359:                && width(tree(newep->focus)) >= 0;
                    360:        while (!atlinestart(oldep) || !atlinestart(newep)) {
                    361:                /* Find beginning of lines for both */
                    362:                if (!up(&newep->focus)) {
                    363:                        Assert(!up(&newep->focus));
                    364:                        break;
                    365:                }
                    366:                --oldpl;
                    367:                up(&oldep->focus) || Abort();
                    368:                --newpl;
                    369:        }
                    370:        if (intraline)
                    371:                return atlinestart(oldep);
                    372:        w = width(tree(oldep->focus));
                    373:        return w < 0 ? -w : 0;
                    374: }
                    375: 
                    376: 
                    377: /*
                    378:  * Initialization code.
                    379:  */
                    380: 
                    381: Visible Procedure
                    382: initshow()
                    383: {
                    384:        int flags = 0;
                    385: #ifndef NDEBUG
                    386:        if (dflag)
                    387:                fprintf(stderr, "*** initshow();\n\r");
                    388: #endif NDEBUG
                    389:        if (!trmstart(&winheight, &llength, &flags)) {
                    390:                endunix();
                    391:                exit(2);
                    392:        }
                    393:        noscroll = (flags&2) == 0;
                    394:        nosense = (flags&8) == 0;
                    395:        winstart = --winheight;
                    396: }
                    397: 
                    398: 
                    399: /*
                    400:  * Routine to move the cursor to the first line after the just edited
                    401:  * document.  (Called after each editing action.)
                    402:  */
                    403: 
                    404: Visible Procedure
                    405: endshow()
                    406: {
                    407:        register cell *p;
                    408:        register int last = winheight;
                    409: 
                    410:        for (p = tops; p; p = p->c_link) {
                    411:                if (p->c_onscreen != Nowhere)
                    412:                        last = p->c_onscreen + Oldspace(p);
                    413:        }
                    414:        if (last > winheight)
                    415:                last = winheight;
                    416:        discard(tops);
                    417:        tops = Cnil;
                    418:        trmputdata(last, winheight, 0, "");
                    419:        trmsync(last, 0);
                    420:        trmend();
                    421: }
                    422: 
                    423: 
                    424: /*
                    425:  * Translate a cursor position in tree coordinates.
                    426:  *
                    427:  * ***** DOESN'T WORK IF SCREEN INDENT DIFFERS FROM TREE INDENT! *****
                    428:  * (I.e. for lines with >= 80 spaces indentation)
                    429:  */
                    430: 
                    431: Visible bool
                    432: backtranslate(py, px)
                    433:        int *py;
                    434:        int *px;
                    435: {
                    436:        cell *p;
                    437:        int y = *py;
                    438:        int x = *px;
                    439:        int i;
                    440: 
                    441:        for (i = 0, p = tops; p; ++i, p = p->c_link) {
                    442:                if (p->c_onscreen != Nowhere
                    443:                        && y >= p->c_onscreen && y < p->c_onscreen + Space(p)) {
                    444:                        *px += (y - p->c_onscreen) * llength - indent;
                    445:                        if (*px < 0)
                    446:                                *px = 0;
                    447:                        *py = i;
                    448:                        if (p->c_oldvhole && (y > focy || y == focy && x > focx))
                    449:                                --*px; /* Correction if beyond Vhole on same logical line */
                    450:                        return Yes;
                    451:                }
                    452:        }
                    453:        error(GOTO_OUT);
                    454:        return No;
                    455: }
                    456: 
                    457: 
                    458: /*
                    459:  * Set the indent level and window start line.
                    460:  */
                    461: 
                    462: Visible Procedure
                    463: setindent(x)
                    464:        int x;
                    465: {
                    466:        winstart= winheight;
                    467:        indent= x;
                    468: }
                    469: 
                    470: 
                    471: /*
                    472:  * Show the command prompt.
                    473:  */
                    474: 
                    475: Visible Procedure cmdprompt(prompt)
                    476:        string prompt;
                    477: {
                    478:        setindent(strlen(prompt));
                    479:        trmputdata(winstart, winstart, 0, prompt);
                    480: }

unix.superglobalmegacorp.com

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