|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: static char rcsid[] = "$Header: outp.c,v 2.4 85/08/22 16:05:48 timo Exp $"; ! 3: ! 4: /* ! 5: * B editor -- Screen management package, lower level output part. ! 6: */ ! 7: ! 8: #include <ctype.h> ! 9: ! 10: #include "b.h" ! 11: #include "bobj.h" ! 12: #include "node.h" ! 13: #include "supr.h" ! 14: #include "gram.h" ! 15: #include "cell.h" ! 16: ! 17: ! 18: #define SOBIT 0200 ! 19: #define CHAR 0177 ! 20: ! 21: ! 22: /* ! 23: * Variables used for communication with outfocus. ! 24: */ ! 25: ! 26: Hidden node thefocus; ! 27: Hidden environ wherebuf; ! 28: Hidden environ *where = &wherebuf; ! 29: Hidden bool realvhole; ! 30: Hidden int multiline; /* Height of focus */ ! 31: Hidden int yfocus; ! 32: ! 33: Visible int focy; /* Where the cursor must go */ ! 34: Visible int focx; ! 35: ! 36: ! 37: /* ! 38: * Save position of the focus for use by outnode/outfocus. ! 39: */ ! 40: ! 41: Visible Procedure ! 42: savefocus(ep) ! 43: register environ *ep; ! 44: { ! 45: register int sym; ! 46: register int w; ! 47: ! 48: realvhole = No; ! 49: thefocus = Nnil; ! 50: multiline = 0; ! 51: yfocus = Ycoord(ep->focus); ! 52: w = focoffset(ep); ! 53: if (w < 0) ! 54: yfocus += -w; ! 55: w = focwidth(ep); ! 56: if (w < 0) { ! 57: multiline = -w; ! 58: if (focchar(ep) == '\n') ! 59: ++yfocus; ! 60: else ! 61: ++multiline; ! 62: return; ! 63: } ! 64: if (ep->mode == WHOLE) { ! 65: sym = symbol(tree(ep->focus)); ! 66: if (sym == Optional) ! 67: ep->mode = ATBEGIN; ! 68: } ! 69: switch(ep->mode) { ! 70: case VHOLE: ! 71: if (ep->s1&1) ! 72: ep->mode = FHOLE; ! 73: case ATBEGIN: ! 74: case ATEND: ! 75: case FHOLE: ! 76: ritevhole(ep); ! 77: switch (ep->mode) { ! 78: case ATBEGIN: ! 79: case FHOLE: ! 80: sym = symbol(tree(ep->focus)); ! 81: if (sym == Hole && (ep->mode == ATBEGIN || ep->s2 == 0)) { ! 82: ep->mode = WHOLE; ! 83: break; ! 84: } ! 85: /* Fall through */ ! 86: case VHOLE: ! 87: case ATEND: ! 88: leftvhole(ep); ! 89: realvhole = 1 + ep->spflag; ! 90: } ! 91: } ! 92: touchpath(&ep->focus); /* Make sure it is a unique pointer */ ! 93: thefocus = tree(ep->focus); /* No copy; used for comparison only! */ ! 94: where->mode = ep->mode; ! 95: where->s1 = ep->s1; ! 96: where->s2 = ep->s2; ! 97: where->s3 = ep->s3; ! 98: where->spflag = ep->spflag; ! 99: } ! 100: ! 101: ! 102: /* ! 103: * Incorporate the information saved about the focus. ! 104: */ ! 105: ! 106: Visible Procedure ! 107: setfocus(tops) ! 108: register cell *tops; ! 109: { ! 110: register cell *p; ! 111: register int i; ! 112: ! 113: for (p = tops, i = 0; i < yfocus; ++i, p = p->c_link) { ! 114: if (!p) { ! 115: #ifndef NDEBUG ! 116: debug("[Focus lost (setfocus)]"); ! 117: #endif NDEBUG ! 118: return; ! 119: } ! 120: } ! 121: p->c_newvhole = realvhole; ! 122: i = multiline; ! 123: do { ! 124: p->c_newfocus = Yes; ! 125: p = p->c_link; ! 126: } while (--i > 0); ! 127: } ! 128: ! 129: ! 130: /* ! 131: * Signal that actual updata is started. ! 132: */ ! 133: ! 134: Visible Procedure ! 135: startactupdate(nofocus) ! 136: bool nofocus; ! 137: { ! 138: if (nofocus) { ! 139: multiline = 0; ! 140: thefocus = Nnil; ! 141: } ! 142: } ! 143: ! 144: ! 145: /* ! 146: * Signal the end of the actual update. ! 147: */ ! 148: ! 149: Visible Procedure ! 150: endactupdate() ! 151: { ! 152: } ! 153: ! 154: ! 155: /* ! 156: * Output a line of text. ! 157: */ ! 158: ! 159: Visible Procedure ! 160: outline(p, lineno) ! 161: register cell *p; ! 162: register int lineno; ! 163: { ! 164: register node n = p->c_data; ! 165: register int w = width(n); ! 166: register string buf = ! 167: malloc((unsigned) (p->c_newindent + 4 + (w < 0 ? linelen(n) : w))); ! 168: /* some 4 extra for spflag and vhole */ ! 169: auto string bp = buf; ! 170: register int i; ! 171: register int endarea = lineno+Space(p)-1; ! 172: ! 173: if (endarea >= winheight) ! 174: endarea = winheight-1; ! 175: for (i = p->c_newindent; i-- > 0; ) ! 176: *bp++ = ' '; ! 177: if (!p->c_newfocus) { ! 178: smash(&bp, n, 0); ! 179: *bp = 0; ! 180: } ! 181: else { ! 182: if (multiline) ! 183: smash(&bp, n, SOBIT); ! 184: else if (n == thefocus) ! 185: focsmash(&bp, n); ! 186: else ! 187: smash(&bp, n, 0); ! 188: *bp = 0; ! 189: for (bp = buf; *bp && !(*bp&SOBIT); ++bp) ! 190: ; ! 191: if (*bp&SOBIT) { ! 192: if (focy == Nowhere) { ! 193: focx = indent + bp-buf; ! 194: focy = lineno + focx/llength; ! 195: focx %= llength; ! 196: } ! 197: if (multiline <= 1 && !(bp[1]&SOBIT)) ! 198: *bp &= ~SOBIT; /* Clear mask if just one char in focus */ ! 199: } ! 200: } ! 201: trmputdata(lineno, endarea, indent, buf); ! 202: } ! 203: ! 204: ! 205: /* ! 206: * Smash -- produce a linear version of a node in a buffer (which had ! 207: * better be long enough!). The buffer pointer is moved to the end of ! 208: * the resulting string. ! 209: * Care is taken to represent the focus. ! 210: * Characters in the focus have their upper bit set. ! 211: */ ! 212: ! 213: #define Outvhole() \ ! 214: (where->spflag && strsmash(pbuf, " ", 0), strsmash(pbuf, "?", SOBIT)) ! 215: ! 216: Hidden Procedure ! 217: focsmash(pbuf, n) ! 218: string *pbuf; ! 219: node n; ! 220: { ! 221: value v; ! 222: string str; ! 223: register string *rp; ! 224: register int maxs2; ! 225: register int i; ! 226: register bool ok; ! 227: register int j; ! 228: register int mask; ! 229: ! 230: switch (where->mode) { ! 231: ! 232: case WHOLE: ! 233: smash(pbuf, n, SOBIT); ! 234: break; ! 235: ! 236: case ATBEGIN: ! 237: Outvhole(); ! 238: smash(pbuf, n, 0); ! 239: break; ! 240: ! 241: case ATEND: ! 242: smash(pbuf, n, 0); ! 243: Outvhole(); ! 244: break; ! 245: ! 246: case VHOLE: ! 247: if (!(where->s1&1)) { ! 248: v = (value) child(n, where->s1/2); ! 249: Assert(Type(v) == Tex); ! 250: subsmash(pbuf, Str(v), where->s2, 0); ! 251: Outvhole(); ! 252: strsmash(pbuf, Str(v) + where->s2, 0); ! 253: break; ! 254: } ! 255: /* Else, fall through */ ! 256: case FHOLE: ! 257: rp = noderepr(n); ! 258: maxs2 = 2*nchildren(n) + 1; ! 259: for (ok = Yes, i = 1; ok && i <= maxs2; ++i) { ! 260: if (i&1) { ! 261: if (i == where->s1) { ! 262: subsmash(pbuf, rp[i/2], where->s2, 0); ! 263: Outvhole(); ! 264: if (rp[i/2]) ! 265: strsmash(pbuf, rp[i/2] + where->s2, 0); ! 266: } ! 267: else ! 268: strsmash(pbuf, rp[i/2], 0); ! 269: } ! 270: else ! 271: ok = chismash(pbuf, n, i/2, 0); ! 272: } ! 273: break; ! 274: ! 275: case SUBRANGE: ! 276: rp = noderepr(n); ! 277: maxs2 = 2*nchildren(n) + 1; ! 278: for (ok = Yes, i = 1; ok && i <= maxs2; ++i) { ! 279: if (i&1) { ! 280: if (i == where->s1) { ! 281: subsmash(pbuf, rp[i/2], where->s2,0); ! 282: if (rp[i/2]) ! 283: subsmash(pbuf, rp[i/2] + where->s2, ! 284: where->s3 - where->s2 + 1, SOBIT); ! 285: if (rp[i/2]) ! 286: strsmash(pbuf, rp[i/2] + where->s3 + 1, 0); ! 287: } ! 288: else ! 289: strsmash(pbuf, rp[i/2], 0); ! 290: } ! 291: else if (i == where->s1) { ! 292: v = (value)child(n, i/2); ! 293: Assert(Type(v) == Tex); ! 294: str = Str(v); ! 295: subsmash(pbuf, str, where->s2, 0); ! 296: subsmash(pbuf, str + where->s2, where->s3 - where->s2 + 1, ! 297: SOBIT); ! 298: strsmash(pbuf, str + where->s3 + 1, 0); ! 299: } ! 300: else ! 301: ok = chismash(pbuf, n, i/2, 0); ! 302: } ! 303: break; ! 304: ! 305: case SUBLIST: ! 306: for (ok = Yes, j = where->s3; j > 0; --j) { ! 307: rp = noderepr(n); ! 308: maxs2 = 2*nchildren(n) - 1; ! 309: for (i = 1; ok && i <= maxs2; ++i) { ! 310: if (i&1) ! 311: strsmash(pbuf, rp[i/2], SOBIT); ! 312: else ! 313: ok = chismash(pbuf, n, i/2, SOBIT); ! 314: } ! 315: if (ok) ! 316: n = lastchild(n); ! 317: } ! 318: if (ok) ! 319: smash(pbuf, n, 0); ! 320: break; ! 321: ! 322: case SUBSET: ! 323: rp = noderepr(n); ! 324: maxs2 = 2*nchildren(n) + 1; ! 325: mask = 0; ! 326: for (ok = Yes, i = 1; ok && i <= maxs2; ++i) { ! 327: if (i == where->s1) ! 328: mask = SOBIT; ! 329: if (i&1) ! 330: strsmash(pbuf, rp[i/2], mask); ! 331: else ! 332: ok = chismash(pbuf, n, i/2, mask); ! 333: if (i == where->s2) ! 334: mask = 0; ! 335: } ! 336: break; ! 337: ! 338: default: ! 339: Abort(); ! 340: } ! 341: } ! 342: ! 343: Hidden Procedure ! 344: smash(pbuf, n, mask) ! 345: register string *pbuf; ! 346: register node n; ! 347: register int mask; ! 348: { ! 349: register string *rp; ! 350: register int i; ! 351: register int nch; ! 352: ! 353: rp = noderepr(n); ! 354: strsmash(pbuf, rp[0], mask); ! 355: nch = nchildren(n); ! 356: for (i = 1; i <= nch; ++i) { ! 357: if (!chismash(pbuf, n, i, mask)) ! 358: break; ! 359: strsmash(pbuf, rp[i], mask); ! 360: } ! 361: } ! 362: ! 363: Hidden Procedure ! 364: strsmash(pbuf, str, mask) ! 365: register string *pbuf; ! 366: register string str; ! 367: register int mask; ! 368: { ! 369: if (!str) ! 370: return; ! 371: for (; *str; ++str) { ! 372: if (isprint(*str) || *str == ' ') ! 373: **pbuf = *str|mask, ++*pbuf; ! 374: } ! 375: } ! 376: ! 377: Hidden Procedure ! 378: subsmash(pbuf, str, len, mask) ! 379: register string *pbuf; ! 380: register string str; ! 381: register int len; ! 382: register int mask; ! 383: { ! 384: if (!str) ! 385: return; ! 386: for (; len > 0 && *str; --len, ++str) { ! 387: if (isprint(*str) || *str == ' ') ! 388: **pbuf = *str|mask, ++*pbuf; ! 389: } ! 390: } ! 391: ! 392: ! 393: /* ! 394: * Smash a node's child. ! 395: * Return No if it contained a newline (to stop the parent). ! 396: */ ! 397: ! 398: Hidden bool ! 399: chismash(pbuf, n, i, mask) ! 400: register string *pbuf; ! 401: register node n; ! 402: register int i; ! 403: { ! 404: register node nn = child(n, i); ! 405: register int w; ! 406: ! 407: if (Type(nn) == Tex) { ! 408: strsmash(pbuf, Str((value)nn), mask); ! 409: return Yes; ! 410: } ! 411: w = width(nn); ! 412: if (w < 0 && Fw_negative(noderepr(nn)[0])) ! 413: return No; ! 414: if (nn == thefocus) ! 415: focsmash(pbuf, nn); ! 416: else ! 417: smash(pbuf, nn, mask); ! 418: return w >= 0; ! 419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.