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

Defined functions

chismash defined in line 398; used 5 times
endactupdate defined in line 149; used 1 times
focsmash defined in line 216; used 2 times
outline defined in line 159; used 2 times
savefocus defined in line 41; used 1 times
setfocus defined in line 106; used 1 times
smash defined in line 343; used 8 times
startactupdate defined in line 134; used 1 times
strsmash defined in line 363; used 13 times
subsmash defined in line 377; used 6 times

Defined variables

focx defined in line 34; used 5 times
focy defined in line 33; used 7 times
multiline defined in line 30; used 7 times
rcsid defined in line 2; never used
realvhole defined in line 29; used 3 times
thefocus defined in line 26; used 5 times
yfocus defined in line 31; used 4 times

Defined macros

CHAR defined in line 19; never used
Outvhole defined in line 213; used 4 times
SOBIT defined in line 18; used 12 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3678
Valid CSS Valid XHTML 1.0 Strict