# 2.11BSD#431 - /usr/src/new/PORT/B/src/bed/cell.c

##### Functions

    build             X
    discard           X
    dupmatch          X
    feedfreelist      X
    gettop            X
    newcell           X
    replist           X

##### Variables

    Hidden            X
    Procedure         X
    Visible           X
    freelist          X

##### Macros

    CELLSIZE          X
    MALLOCLOSS        X
    PAGESIZE          X

       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: }

#### Defined functions

build defined in line 204; used 2 times

- in /usr/src/new/PORT/B/src/bed/cell.h line 35
- in /usr/src/new/PORT/B/src/bed/scrn.c line 304

discard defined in line 135; used 3 times

- in line 84
- in /usr/src/new/PORT/B/src/bed/scrn.c line 271, 416

dupmatch defined in line 161; used 1 times

- in line 83

feedfreelist defined in line 115; used 1 times

- in line 101

gettop defined in line 252; used 2 times

- in /usr/src/new/PORT/B/src/bed/scrn.c line 19, 58

newcell defined in line 95; used 1 times

- in line 214

replist defined in line 42; used 2 times

- in /usr/src/new/PORT/B/src/bed/cell.h line 34
- in /usr/src/new/PORT/B/src/bed/scrn.c line 304

#### Defined variables

Hidden defined in line 115; never used
Procedure defined in line 135; never used
Visible defined in line 135; never used
freelist defined in line 22; used 6 times

- in line 100-103(3), 124, 151-152(2)

rcsid defined in line 2; never used

#### Defined macros

CELLSIZE defined in line 24; used 2 times

- in line 118-119(2)

MALLOCLOSS defined in line 31; used 2 times

- in line 30, 118

PAGESIZE defined in line 27; used 2 times

- in line 26, 118

Last modified: 1985-08-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 896 |