Annotation of 43BSDTahoe/new/B/src/bed/scrn.c, revision 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.