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