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

Defined functions

actupdate defined in line 39; used 2 times
atlinestart defined in line 313; used 5 times
backtranslate defined in line 431; used 1 times
cmdprompt defined in line 475; used 1 times
endshow defined in line 404; used 3 times
fixlevels defined in line 329; used 2 times
growwin defined in line 128; used 1 times
  • in line 56
initshow defined in line 381; used 3 times
make2room defined in line 222; used 2 times
makeroom defined in line 159; used 1 times
  • in line 88
setindent defined in line 462; used 2 times
virtupdate defined in line 254; used 1 times

Defined variables

noscroll defined in line 29; used 3 times
nosense defined in line 30; used 2 times
rcsid defined in line 2; never used
tops defined in line 32; used 14 times
winheight defined in line 25; used 86 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3495
Valid CSS Valid XHTML 1.0 Strict