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
Defined variables
rcsid
defined in line
2;
never used