home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
- static char rcsid[] = "$Header: line.c,v 2.4 85/08/22 16:04:53 timo Exp $";
-
- /*
- * B editor -- Routines for treating the parse tree as a sequence of lines.
- *
- * WARNING: The routines in this file (and many others!) assume that a
- * `newline' can only occur in the zero'th representation string of a node
- * (i.e., rp[0]).
- */
-
- #include "b.h"
- #include "bobj.h"
- #include "node.h"
- #include "gram.h"
- #include "supr.h"
-
-
- /*
- * Compute equality of subtrees, based on common descent.
- * Strings are not checked for characterwise equality, but must
- * be the same pointer; other nodes must have the same symbol and
- * their children must be equal in this sense (equal pointers are
- * always used as a shortcut).
- *
- * (Used by screen update algorithm only.)
- */
-
- Visible bool
- eqlines(n1, n2)
- node n1;
- node n2;
- {
- register node nn1;
- register node nn2;
- register int w1;
- register int w2;
- register int nch;
- register int i;
-
- if (n1 == n2)
- return Yes;
- if (Type(n1) != Nod || Type(n2) != Nod)
- return No;
- if (symbol(n1) != symbol(n2))
- return No;
- nch = nchildren(n1);
- Assert(nch == nchildren(n2));
- for (i = 1; i <= nch; ++i) {
- nn1 = child(n1, i);
- nn2 = child(n2, i);
- w1 = width(nn1);
- w2 = width(nn2);
- if (w1 >= 0 && w2 >= 0) {
- if (!eqlines(nn1, nn2))
- return No;
- }
- else {
- if (nn1 == nn2)
- return Yes;
- if (fwidth(noderepr(nn1)[0]) < 0 || fwidth(noderepr(nn2)[0]) < 0)
- return linelen(n1) == linelen(n2);
- return eqlines(nn1, nn2);
- }
- }
- return Yes;
- }
-
-
- /*
- * Compute the length of the line beginning at the current node.
- */
-
- Visible int
- linelen(n)
- node n;
- {
- register node nn;
- register string *rp = noderepr(n);
- register int w;
- register int nch = nchildren(n);
- register int i;
- register int len = fwidth(rp[0]);
-
- if (len < 0)
- len = 0;
- for (i = 1; i <= nch; ++i) {
- nn = child(n, i);
- w = width(nn);
- if (w >= 0)
- len += w;
- else {
- n = nn;
- i = 0;
- nch = nchildren(n);
- rp = noderepr(n);
- }
- w = Fwidth(rp[i]);
- if (w < 0)
- break;
- len += w;
- }
- return len;
- }
-
-
- /*
- * Move the focus to the next line.
- * NB: This is a building block for use in the 'show' module;
- * it cannot set ep->mode or call higher() properly!
- */
-
- Visible bool
- nextline(pp)
- register path *pp;
- {
- register node n;
- register node nn;
- register int w;
- register int nch;
- register int i = 0;
-
- for (;;) {
- n = tree(*pp);
- if (width(n) < 0) {
- nch = nchildren(n);
- while (++i <= nch) {
- nn = child(n, i);
- w = width(nn);
- if (w < 0) {
- downi(pp, i) || Abort();
- n = tree(*pp);
- if (fwidth(noderepr(n)[0]) < 0)
- return Yes;
- nch = nchildren(n);
- i = 0;
- }
- }
- }
- /* Must go upward in the tree */
- i = ichild(*pp);
- if (!up(pp))
- return No;
- }
- }
-
-
- /*
- * Compute the current line number. If the current node begins with
- * a `newline', add one because the first character is actually
- * on the next line.
- */
-
- Visible int
- lineno(ep)
- register environ *ep;
- {
- register int y;
-
- y = -focoffset(ep);
- if (y < 0)
- y = 0;
- if (focchar(ep) == '\n')
- ++y;
- return y + Ycoord(ep->focus);
- }
-
- /*
- * Similarly, compute the current column number.
- * (Hope the abovementioned trick isn't necessary.)
- */
-
- Visible int
- colno(ep)
- environ *ep;
- {
- int x= focoffset(ep);
-
- if (x < 0)
- x= 0; /* In fact, give up */
- return x + Xcoord(ep->focus);
- }
-
-
- /*
- * Make the focus exactly one line wide (if at all possible).
- */
-
- Visible Procedure
- oneline(ep)
- register environ *ep;
- {
- register node n;
- node nn;
- register string *rp;
- register int s1;
- register int s2;
- register int len;
- int ich;
- int nch;
-
- ich = 1;
- while (width(tree(ep->focus)) >= 0) {
- ich = ichild(ep->focus);
- if (!up(&ep->focus)) {
- ep->mode = WHOLE;
- higher(ep);
- return;
- }
- }
- higher(ep);
- n = tree(ep->focus);
- nch = nchildren(n);
- rp = noderepr(n);
- for (s1 = 2*ich-1; s1 >= 1; --s1) {
- if (s1&1)
- len = fwidth(rp[s1/2]);
- else {
- nn = child(n, s1/2);
- len = width(nn);
- }
- if (len < 0)
- break;
- }
- for (s2 = 2*ich+1; s2 <= 2*nch+1; ++s2) {
- if (s2&1)
- len = fwidth(rp[s2/2]);
- else {
- nn = child(n, s2/2);
- len = width(nn);
- }
- if (len < 0)
- break;
- }
- ep->mode = SUBSET;
- ep->s1 = s1+1;
- ep->s2 = s2-1;
- }
-