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