1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
   2: static char rcsid[] = "$Header: eval.c,v 2.3 84/07/19 11:47:18 guido Exp $";
   3: 
   4: /*
   5:  * B editor -- Width attribute evaluation.
   6:  */
   7: 
   8: #include "b.h"
   9: #include "node.h"
  10: #include "gram.h"
  11: #include "eval.h"
  12: 
  13: 
  14: /*
  15:  * The following convention is used throughout the editor to indicate
  16:  * the sizes of objects.
  17:  * - A zero or positive `width' value means the object contains no
  18:  *   linefeeds.  The width is counted in characters.
  19:  * - A negative `width' means the object (or its children) contains
  20:  *   at leasty one linefeed (return is treated as a linefeed here).
  21:  *   The number of linefeeds is -width.
  22:  *   There is no indication whether the object fits on that number of
  23:  *   physical lines, as logical lines may have arbitrary length.
  24:  *
  25:  * For coordinates the following convention is used.
  26:  * (Note that, in accordance to the convention in curses(3), the
  27:  * `y' coordinate always precedes the `x' coorxdinate.)
  28:  * - `Y' is the line number, counted from the beginning of the unit.
  29:  *   These are logical lines rather than physical lines.
  30:  *   The first line has line number 0.
  31:  * - `X' is the column number.  The first column is 0.  For x < 0,
  32:  *   see the important notice below.
  33:  * - `Level' is the indentation level, indicating where a new line
  34:  *   would start if inserted at the current position.
  35:  *   The initial `x' position of such a line is `level*TABS'.
  36:  *
  37:  * ***** IMPORTANT NOTICE *****
  38:  * A special case is x = -1.  This means that the current x position is
  39:  * unknown.  Further output on the same line is suppressed, until a
  40:  * linefeed is encountered.  This feature is necessary because while
  41:  * calculating coordinates, when an object has width < 0, only the y
  42:  * coordinate of the end of that object is known.  In this case, the
  43:  * next non-empty object MUST START WITH A LINEFEED, or it will not
  44:  * be visible on the screen (in practice, a space is sometimes present
  45:  * in the parse tree which is not shown then).
  46:  */
  47: 
  48: 
  49: /*
  50:  * Compute the (y, x) coordinates and indent level just before
  51:  * the beginning of the j'th child, if the current node starts
  52:  * at the initial values of (y, x) and level.
  53:  */
  54: 
  55: Visible Procedure
  56: evalcoord(n, jch, py, px, plevel)
  57:     register node n;
  58:     register int jch;
  59:     int *py;
  60:     int *px;
  61:     int *plevel;
  62: {
  63:     node nn;
  64:     register int i;
  65:     register string *rp = noderepr(n);
  66:     register int k;
  67:     register int y = 0;
  68:     int x = *px;
  69:     int level = *plevel;
  70:     int nch = Type(n) == Tex ? 0 : nchildren(n);
  71: 
  72:     if (jch > nch)
  73:         jch = nch+1;
  74:     for (i = 0; i < jch; ++i) {
  75:         if (i) {
  76:             nn = child(n, i);
  77:             k = width(nn);
  78:             if (k < 0) {
  79:                 y += -k;
  80:                 x = k;
  81:             }
  82:             else if (x >= 0)
  83:                 x += k;
  84:         }
  85:         k = Fwidth(rp[i]);
  86:         if (k < 0) {
  87:             y += -k;
  88:             x = rp[i][0] == '\r' ? 0 : TABS*level;
  89:             x += strlen(rp[i]) - 1;
  90:         }
  91:         else {
  92:             if (x >= 0)
  93:                 x += k;
  94:             if (rp[i]) {
  95:                 if (rp[i][k] == '\t')
  96:                     ++level;
  97:                 else if (rp[i][k] == '\b')
  98:                     --level;
  99:             }
 100:         }
 101:     }
 102: 
 103:     *py += y;
 104:     *px = x;
 105:     *plevel = level;
 106: }
 107: 
 108: 
 109: /*
 110:  * Yield the width of a piece of fixed text as found in a node's repr,
 111:  * excluding \b or \t.  If \n or \r is found, -1 is returned.
 112:  * It assumes that \n or \r only occur as first
 113:  * character, and \b or \t only as last.
 114:  */
 115: 
 116: Visible int
 117: fwidth(str)
 118:     register string str;
 119: {
 120:     register int c;
 121:     register int n = 0;
 122: 
 123:     if (!str)
 124:         return 0;
 125:     c = str[0];
 126:     if (c == '\r' || c == '\n')
 127:         return -1;
 128:     for (; c; c = *++str)
 129:         ++n;
 130:     if (n > 0) {
 131:         c = str[-1];
 132:         if (c == '\t' || c == '\b')
 133:             --n;
 134:     }
 135:     return n;
 136: }
 137: 
 138: 
 139: /*
 140:  * Evaluate the width of node n, assuming the widths of its children
 141:  * have correctly been calculated.
 142:  */
 143: 
 144: Visible int
 145: evalwidth(n)
 146:     register node n;
 147: {
 148:     register int w;
 149:     register int i;
 150:     register string *rp;
 151:     register int y = 0;
 152:     register int x = 0;
 153:     register int nch;
 154:     register node nn;
 155: 
 156:     rp = noderepr(n);
 157:     nch = Type(n) == Tex ? 0 : nchildren(n);
 158:     for (i = 0; i <= nch; ++i) {
 159:         if (i) {
 160:             nn = child(n, i);
 161:             w = width(nn);
 162:             if (w < 0) {
 163:                 y += -w;
 164:                 x = w;
 165:             }
 166:             else
 167:                 x += w;
 168:         }
 169:         w = Fwidth(rp[i]);
 170:         if (w < 0) {
 171:             y += -w;
 172:             x = 0;
 173:         }
 174:         else
 175:             x += w;
 176:     }
 177:     if (y > 0)
 178:         return -y;
 179:     return x;
 180: }
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2254
Valid CSS Valid XHTML 1.0 Strict