|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.