1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
   2: static char rcsid[] = "$Header: line.c,v 2.4 85/08/22 16:04:53 timo Exp $";
   3: 
   4: /*
   5:  * B editor -- Routines for treating the parse tree as a sequence of lines.
   6:  *
   7:  * WARNING: The routines in this file (and many others!) assume that a
   8:  * `newline' can only occur in the zero'th representation string of a node
   9:  * (i.e., rp[0]).
  10:  */
  11: 
  12: #include "b.h"
  13: #include "bobj.h"
  14: #include "node.h"
  15: #include "gram.h"
  16: #include "supr.h"
  17: 
  18: 
  19: /*
  20:  * Compute equality of subtrees, based on common descent.
  21:  * Strings are not checked for characterwise equality, but must
  22:  * be the same pointer; other nodes must have the same symbol and
  23:  * their children must be equal in this sense (equal pointers are
  24:  * always used as a shortcut).
  25:  *
  26:  * (Used by screen update algorithm only.)
  27:  */
  28: 
  29: Visible bool
  30: eqlines(n1, n2)
  31:     node n1;
  32:     node n2;
  33: {
  34:     register node nn1;
  35:     register node nn2;
  36:     register int w1;
  37:     register int w2;
  38:     register int nch;
  39:     register int i;
  40: 
  41:     if (n1 == n2)
  42:         return Yes;
  43:     if (Type(n1) != Nod || Type(n2) != Nod)
  44:         return No;
  45:     if (symbol(n1) != symbol(n2))
  46:         return No;
  47:     nch = nchildren(n1);
  48:     Assert(nch == nchildren(n2));
  49:     for (i = 1; i <= nch; ++i) {
  50:         nn1 = child(n1, i);
  51:         nn2 = child(n2, i);
  52:         w1 = width(nn1);
  53:         w2 = width(nn2);
  54:         if (w1 >= 0 && w2 >= 0) {
  55:             if (!eqlines(nn1, nn2))
  56:                 return No;
  57:         }
  58:         else {
  59:             if (nn1 == nn2)
  60:                 return Yes;
  61:             if (fwidth(noderepr(nn1)[0]) < 0 || fwidth(noderepr(nn2)[0]) < 0)
  62:                 return linelen(n1) == linelen(n2);
  63:             return eqlines(nn1, nn2);
  64:         }
  65:     }
  66:     return Yes;
  67: }
  68: 
  69: 
  70: /*
  71:  * Compute the length of the line beginning at the current node.
  72:  */
  73: 
  74: Visible int
  75: linelen(n)
  76:     node n;
  77: {
  78:     register node nn;
  79:     register string *rp = noderepr(n);
  80:     register int w;
  81:     register int nch = nchildren(n);
  82:     register int i;
  83:     register int len = fwidth(rp[0]);
  84: 
  85:     if (len < 0)
  86:         len = 0;
  87:     for (i = 1; i <= nch; ++i) {
  88:         nn = child(n, i);
  89:         w = width(nn);
  90:         if (w >= 0)
  91:             len += w;
  92:         else {
  93:             n = nn;
  94:             i = 0;
  95:             nch = nchildren(n);
  96:             rp = noderepr(n);
  97:         }
  98:         w = Fwidth(rp[i]);
  99:         if (w < 0)
 100:             break;
 101:         len += w;
 102:     }
 103:     return len;
 104: }
 105: 
 106: 
 107: /*
 108:  * Move the focus to the next line.
 109:  * NB: This is a building block for use in the 'show' module;
 110:  * it cannot set ep->mode or call higher() properly!
 111:  */
 112: 
 113: Visible bool
 114: nextline(pp)
 115:     register path *pp;
 116: {
 117:     register node n;
 118:     register node nn;
 119:     register int w;
 120:     register int nch;
 121:     register int i = 0;
 122: 
 123:     for (;;) {
 124:         n = tree(*pp);
 125:         if (width(n) < 0) {
 126:             nch = nchildren(n);
 127:             while (++i <= nch) {
 128:                 nn = child(n, i);
 129:                 w = width(nn);
 130:                 if (w < 0) {
 131:                     downi(pp, i) || Abort();
 132:                     n = tree(*pp);
 133:                     if (fwidth(noderepr(n)[0]) < 0)
 134:                         return Yes;
 135:                     nch = nchildren(n);
 136:                     i = 0;
 137:                 }
 138:             }
 139:         }
 140:         /* Must go upward in the tree */
 141:         i = ichild(*pp);
 142:         if (!up(pp))
 143:             return No;
 144:     }
 145: }
 146: 
 147: 
 148: /*
 149:  * Compute the current line number.  If the current node begins with
 150:  * a `newline', add one because the first character is actually
 151:  * on the next line.
 152:  */
 153: 
 154: Visible int
 155: lineno(ep)
 156:     register environ *ep;
 157: {
 158:     register int y;
 159: 
 160:     y = -focoffset(ep);
 161:     if (y < 0)
 162:         y = 0;
 163:     if (focchar(ep) == '\n')
 164:         ++y;
 165:     return y + Ycoord(ep->focus);
 166: }
 167: 
 168: /*
 169:  * Similarly, compute the current column number.
 170:  * (Hope the abovementioned trick isn't necessary.)
 171:  */
 172: 
 173: Visible int
 174: colno(ep)
 175:     environ *ep;
 176: {
 177:     int x= focoffset(ep);
 178: 
 179:     if (x < 0)
 180:         x= 0; /* In fact, give up */
 181:     return x + Xcoord(ep->focus);
 182: }
 183: 
 184: 
 185: /*
 186:  * Make the focus exactly one line wide (if at all possible).
 187:  */
 188: 
 189: Visible Procedure
 190: oneline(ep)
 191:     register environ *ep;
 192: {
 193:     register node n;
 194:     node nn;
 195:     register string *rp;
 196:     register int s1;
 197:     register int s2;
 198:     register int len;
 199:     int ich;
 200:     int nch;
 201: 
 202:     ich = 1;
 203:     while (width(tree(ep->focus)) >= 0) {
 204:         ich = ichild(ep->focus);
 205:         if (!up(&ep->focus)) {
 206:             ep->mode = WHOLE;
 207:             higher(ep);
 208:             return;
 209:         }
 210:     }
 211:     higher(ep);
 212:     n = tree(ep->focus);
 213:     nch = nchildren(n);
 214:     rp = noderepr(n);
 215:     for (s1 = 2*ich-1; s1 >= 1; --s1) {
 216:         if (s1&1)
 217:             len = fwidth(rp[s1/2]);
 218:         else {
 219:             nn = child(n, s1/2);
 220:             len = width(nn);
 221:         }
 222:         if (len < 0)
 223:             break;
 224:     }
 225:     for (s2 = 2*ich+1; s2 <= 2*nch+1; ++s2) {
 226:         if (s2&1)
 227:             len = fwidth(rp[s2/2]);
 228:         else {
 229:             nn = child(n, s2/2);
 230:             len = width(nn);
 231:         }
 232:         if (len < 0)
 233:             break;
 234:     }
 235:     ep->mode = SUBSET;
 236:     ep->s1 = s1+1;
 237:     ep->s2 = s2-1;
 238: }

Defined functions

colno defined in line 173; used 1 times
eqlines defined in line 29; used 3 times
linelen defined in line 74; used 4 times
nextline defined in line 113; used 1 times

Defined variables

rcsid defined in line 2; never used
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2311
Valid CSS Valid XHTML 1.0 Strict