Annotation of 43BSDTahoe/new/B/src/bed/cell.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: cell.c,v 2.4 85/02/12 11:18:00 timo Exp $";
        !             3: 
        !             4: /*
        !             5:  * B editor -- Screen management package, cell list manipulation routines.
        !             6:  */
        !             7: 
        !             8: #include "b.h"
        !             9: #include "bobj.h"
        !            10: #include "node.h"
        !            11: #include "eval.h"
        !            12: #include "cell.h"
        !            13: 
        !            14: 
        !            15: extern bool dflag;
        !            16: extern bool noscroll;
        !            17: 
        !            18: /*
        !            19:  * Definitions for internals of cell manipulations.
        !            20:  */
        !            21: 
        !            22: Hidden cell *freelist;
        !            23: 
        !            24: #define CELLSIZE (sizeof(cell))
        !            25: 
        !            26: #ifndef PAGESIZE /* 4.2 BSD freaks compile with -DPAGESIZE='getpagesize()' */
        !            27: #define PAGESIZE 1024
        !            28: #endif
        !            29: 
        !            30: #ifndef MALLOCLOSS
        !            31: #define MALLOCLOSS (sizeof(char*))
        !            32:        /* number of bytes taken by malloc administration per block */
        !            33: #endif
        !            34: 
        !            35: 
        !            36: /*
        !            37:  * Replace `oldlcnt' cells from `tops', starting at the one numbered `oldlno',
        !            38:  * by the list `rep'.
        !            39:  * Returns a pointer to the deleted chain (with a Nil end pointer).
        !            40:  */
        !            41: 
        !            42: Visible cell *
        !            43: replist(tops, rep, oldlno, oldlcnt)
        !            44:        cell *tops;
        !            45:        cell *rep;
        !            46:        int oldlno;
        !            47:        register int oldlcnt;
        !            48: {
        !            49:        cell head;
        !            50:        register cell *p;
        !            51:        register cell *q;
        !            52:        register cell *old;
        !            53:        register cell *end;
        !            54:        register int diff;
        !            55:        int i;
        !            56:        int replcnt;
        !            57: 
        !            58:        if (!tops) /* Start with empty list */
        !            59:                return rep;
        !            60:        head.c_link = tops;
        !            61:        p = &head;
        !            62:        for (diff = oldlno; diff > 0; --diff) {
        !            63:                p = p->c_link;
        !            64:                Assert(p);
        !            65:        }
        !            66:        q = p;
        !            67:        for (i = oldlcnt; i > 0 && p; --i)
        !            68:                p = p->c_link;
        !            69:        if (i > 0) {
        !            70: #ifndef NDEBUG
        !            71:                debug("[replist jackpot]");
        !            72: #endif NDEBUG
        !            73:                oldlcnt -= i;
        !            74:        }
        !            75:        old = q->c_link;
        !            76:        q->c_link = rep;
        !            77:        if (p) {
        !            78:                end = p->c_link;
        !            79:                p->c_link = Cnil;
        !            80:        }
        !            81:        for (replcnt = 0; q->c_link; ++replcnt, q = q->c_link)
        !            82:                ;
        !            83:        dupmatch(old, rep, oldlcnt, replcnt);
        !            84:        discard(old);
        !            85:        if (p)
        !            86:                q->c_link = end;
        !            87:        return head.c_link;
        !            88: }
        !            89: 
        !            90: 
        !            91: /*
        !            92:  * Allocate a new cell.
        !            93:  */
        !            94: 
        !            95: Hidden cell *
        !            96: newcell()
        !            97: {
        !            98:        register cell *p;
        !            99: 
        !           100:        if (!freelist)
        !           101:                feedfreelist();
        !           102:        p = freelist;
        !           103:        freelist = p->c_link;
        !           104:        p->c_link = Cnil;
        !           105:        return p;
        !           106: }
        !           107: 
        !           108: 
        !           109: /*
        !           110:  * Feed the free list with a block of new entries.
        !           111:  * We try to keep them together on a page
        !           112:  * to keep consecutive accesses fast.
        !           113:  */
        !           114: 
        !           115: Hidden Procedure
        !           116: feedfreelist()
        !           117: {
        !           118:        register int n = (PAGESIZE-MALLOCLOSS) / CELLSIZE;
        !           119:        register cell *p = (cell*) malloc((unsigned)(n*CELLSIZE));
        !           120: 
        !           121:        Assert(n > 0);
        !           122:        if (!p)
        !           123:                syserr("feedfreelist: malloc");
        !           124:        freelist = p;
        !           125:        for (; n > 1; --n, ++p)
        !           126:                p->c_link = p+1;
        !           127:        p->c_link = Cnil;
        !           128: }
        !           129: 
        !           130: 
        !           131: /*
        !           132:  * Discard all entries of a list of cells.
        !           133:  */
        !           134: 
        !           135: Visible Procedure
        !           136: discard(p)
        !           137:        register cell *p;
        !           138: {
        !           139:        register cell *savefreelist;
        !           140: 
        !           141:        if (!p)
        !           142:                return;
        !           143:        savefreelist = p;
        !           144:        for (;;) {
        !           145:                noderelease(p->c_data);
        !           146:                p->c_data = Nnil;
        !           147:                if (!p->c_link)
        !           148:                        break;
        !           149:                p = p->c_link;
        !           150:        }
        !           151:        p->c_link = freelist;
        !           152:        freelist = savefreelist;
        !           153: }
        !           154: 
        !           155: 
        !           156: /*
        !           157:  * Replace the `onscreen' fields in the replacement chain by those
        !           158:  * in the old chain, if they match.
        !           159:  */
        !           160: 
        !           161: Hidden Procedure
        !           162: dupmatch(old, rep, oldcnt, repcnt)
        !           163:        register cell *old;
        !           164:        register cell *rep;
        !           165:        int oldcnt;
        !           166:        int repcnt;
        !           167: {
        !           168:        register int diff = repcnt - oldcnt;
        !           169: 
        !           170: #ifndef NDEBUG
        !           171:        if (dflag)
        !           172:                debug("[dupmatch(oldcnt=%d, newcnt=%d)]", oldcnt, repcnt);
        !           173: #endif NDEBUG
        !           174:        while (rep && old) {
        !           175:                if (old->c_length == rep->c_length
        !           176:                        && eqlines(old->c_data, rep->c_data)) {
        !           177:                        if (old->c_onscreen != Nowhere) {
        !           178:                                rep->c_onscreen = old->c_onscreen;
        !           179:                                rep->c_oldindent = old->c_oldindent;
        !           180:                                rep->c_oldvhole = old->c_oldvhole;
        !           181:                                rep->c_oldfocus = old->c_oldfocus;
        !           182:                        }
        !           183:                        rep = rep->c_link;
        !           184:                        old = old->c_link;
        !           185:                }
        !           186:                else {
        !           187:                        if (diff >= 0) {
        !           188:                                --diff;
        !           189:                                rep = rep->c_link;
        !           190:                        }
        !           191:                        if (diff < 0) {
        !           192:                                ++diff;
        !           193:                                old = old->c_link;
        !           194:                        }
        !           195:                }
        !           196:        }
        !           197: }
        !           198: 
        !           199: 
        !           200: /*
        !           201:  * Build a list of cells consisting of the first `lcnt' lines of the tree.
        !           202:  */
        !           203: 
        !           204: Visible cell *
        !           205: build(p, lcnt)
        !           206:        /*auto*/ path p;
        !           207:        register int lcnt;
        !           208: {
        !           209:        cell head;
        !           210:        register cell *q = &head;
        !           211: 
        !           212:        p = pathcopy(p);
        !           213:        for (;;) {
        !           214:                q = q->c_link = newcell();
        !           215:                q->c_onscreen = Nowhere;
        !           216:                q->c_data = nodecopy(tree(p));
        !           217:                q->c_length = linelen(q->c_data);
        !           218:                q->c_newindent = Level(p) * TABS;
        !           219:                q->c_oldindent = 0;
        !           220:                q->c_oldvhole = q->c_newvhole = q->c_oldfocus = q->c_newfocus = No;
        !           221:                --lcnt;
        !           222:                if (lcnt <= 0)
        !           223:                        break;
        !           224:                nextline(&p) || Abort();
        !           225:        }
        !           226:        q->c_link = Cnil;
        !           227:        pathrelease(p);
        !           228:        return head.c_link;
        !           229: }
        !           230: 
        !           231: 
        !           232: /*
        !           233:  * Decide which line is to be on top of the screen.
        !           234:  * We slide a window through the list of lines, recognizing
        !           235:  * lines of the focus and lines already on the screen,
        !           236:  * and stop as soon as we find a reasonable focus position.
        !           237:  *
        !           238:  * - The focus must always be on the screen completely;
        !           239:  *   if it is larger than the screen, its first line must be
        !           240:  *   on top of the screen.
        !           241:  * - When old lines can be retained, at least one line above
        !           242:  *   and below the focus must be shown; the retained lines
        !           243:  *   should be moved as little as possible.
        !           244:  * - As little as possible blank space should be shown at the
        !           245:  *   bottom, even if the focus is at the end of the unit.
        !           246:  * - If no rule applies, try to center the focus on the screen.
        !           247:  * - If noscroll is Yes (the terminal can't scroll), and the top
        !           248:  *   line can't be retained, also try to center the focus on the
        !           249:  *   screen.
        !           250:  */
        !           251: 
        !           252: Visible cell *
        !           253: gettop(tops)
        !           254:        cell *tops;
        !           255: {
        !           256:        register cell *pfwa = tops; /* First line of sliding window */
        !           257:        register cell *plwa = tops; /* Last+1 line of sliding window */
        !           258:        register cell *pffocus = Cnil; /* First line of focus */
        !           259:        cell *pscreen = Cnil; /* First line still on screen */
        !           260:        register int nfwa = 0; /* Corresponding line numbers in parse tree */
        !           261:        register int nlwa = 0;
        !           262:        register int nffocus;
        !           263:        int nlfocus;
        !           264:        int nscreen;
        !           265:        int size;
        !           266: 
        !           267:        for (;;) { /* plwa is the current candidate for top line. */
        !           268:                if (!pfwa) {
        !           269: #ifndef NDEBUG
        !           270:                        debug("[Lost the focus!]");
        !           271: #endif NDEBUG
        !           272:                        return tops; /* To show *something*... */
        !           273:                }
        !           274:                while (plwa && nlwa < nfwa+winheight) {
        !           275:                        /* Find first line *not* in window */
        !           276:                        size = Space(plwa);
        !           277:                        if (plwa->c_newfocus) { /* Hit a focus line */
        !           278:                                if (!pffocus) { /* Note first focus line */
        !           279:                                        pffocus = plwa;
        !           280:                                        nffocus = nlwa;
        !           281:                                }
        !           282:                                nlfocus = nlwa + size;
        !           283:                        }
        !           284:                        if (plwa->c_onscreen != Nowhere) { /* Hello old chap */
        !           285:                                if (!pscreen) { /* Note first line on screen */
        !           286:                                        pscreen = plwa;
        !           287:                                        nscreen = nlwa;
        !           288:                                }
        !           289:                        }
        !           290:                        nlwa += size;
        !           291:                        plwa = plwa->c_link;
        !           292:                }
        !           293:                if (pffocus) {
        !           294:                        /* Focus in sight; stop at first reasonable opportunity */
        !           295:                        if (pffocus == pfwa)
        !           296:                                break; /* Grab last chance! */
        !           297:                        if (!noscroll && nlwa - nfwa <= winheight - winheight/3)
        !           298:                                break; /* Don't show too much white space at bottom */
        !           299:                        if (pffocus == pfwa->c_link && nlfocus < nfwa+winheight)
        !           300:                                break; /* Near top line */
        !           301:                        if (pscreen && (!noscroll || nffocus > nscreen)) {
        !           302:                                /* Conservatism may succeed */
        !           303:                                if (pscreen->c_onscreen >= nscreen - nfwa
        !           304:                                        && (nlfocus < nfwa+winheight
        !           305:                                                || !plwa && nlfocus == nfwa+winheight))
        !           306:                                        break; /* focus entirely on screen */
        !           307:                        }
        !           308:                        else { /* No comrades seen */
        !           309:                                if (nffocus - nfwa <= nfwa+winheight - nlfocus
        !           310:                                        || !plwa && nlwa <= nfwa+winheight)
        !           311:                                        break; /* Nicely centered focus or end of unit */
        !           312:                        }
        !           313:                }
        !           314:                if (pfwa == pscreen) { /* Say farewell to oldest comrade */
        !           315:                        pscreen->c_onscreen = Nowhere;
        !           316:                        do { /* Find next in age */
        !           317:                                nscreen += Space(pscreen);
        !           318:                                pscreen = pscreen->c_link;
        !           319:                                if (pscreen == plwa) {
        !           320:                                        pscreen = Cnil;
        !           321:                                        break;
        !           322:                                }
        !           323:                        } while (pscreen->c_onscreen == Nowhere);
        !           324:                }
        !           325:                nfwa += Space(pfwa);
        !           326:                pfwa = pfwa->c_link; /* Pass the buck */
        !           327:        }
        !           328:        return pfwa; /* This is what all those breaks aim at */
        !           329: }

unix.superglobalmegacorp.com

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