1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: static char rcsid[] = "$Header: goto.c,v 2.4 85/08/22 16:03:06 timo Exp $";
3:
4: /*
5: * B editor -- Random access focus positioning.
6: */
7:
8: #include "b.h"
9: #include "feat.h"
10: #include "erro.h"
11: #include "node.h"
12: #include "gram.h"
13: #include "supr.h"
14:
15:
16: extern int winheight;
17: extern int winstart;
18:
19:
20: #define BEFORE (-1)
21: #define INSIDE 0
22: #define BEYOND 1
23:
24:
25: /*
26: * Random cursor positioning (e.g., with a mouse).
27: */
28:
29: Visible bool
30: gotocursor(ep)
31: environ *ep;
32: {
33: int y;
34: int x;
35:
36: if (!sense(&y, &x))
37: return No;
38: #ifdef SCROLLBAR
39: if (y == winheight)
40: return gotoscrollbar(ep, y, x);
41: #endif SCROLLBAR
42: if (!backtranslate(&y, &x))
43: return No;
44: if (!gotoyx(ep, y, x))
45: return No;
46: gotofix(ep, y, x);
47: return Yes;
48: }
49:
50: #ifdef SCROLLBAR
51:
52: /*
53: * Special case for goto: user pointed at some point in the scroll bar.
54: * Go directly to the corresponding line.
55: * (The scroll bar is only present when winstart == 0; it extends from
56: * col 0 to winheight-1 inclusive.)
57: */
58:
59: Hidden bool
60: gotoscrollbar(ep, y, x)
61: environ *ep;
62: int y;
63: int x;
64: {
65: int w;
66:
67: if (winstart != 0 || x >= winheight) { /* Not within scroll bar */
68: error(GOTO_OUT);
69: return No;
70: }
71: top(&ep->focus);
72: ep->mode = WHOLE;
73: higher(ep);
74: w = width(tree(ep->focus));
75: if (w >= 0)
76: w = 1;
77: else
78: w = 1-w;
79: if (!gotoyx(ep, x * w / winheight, 0))
80: return No;
81: oneline(ep);
82: return Yes;
83: }
84:
85: #endif SCROLLBAR
86:
87: /*
88: * Set the focus to the smallest node or subset surrounding
89: * the position (y, x).
90: */
91:
92: Visible bool
93: gotoyx(ep, y, x)
94: register environ *ep;
95: register int y;
96: register int x;
97: {
98: register node n;
99: register string *rp;
100: register int i;
101: register int pc;
102:
103: ep->mode = WHOLE;
104: while ((pc = poscomp(ep->focus, y, x)) != INSIDE) {
105: if (!up(&ep->focus)) {
106: if (pc == BEFORE)
107: ep->mode = ATBEGIN;
108: else
109: ep->mode = ATEND;
110: higher(ep);
111: return No;
112: }
113: }
114: higher(ep);
115: for (;;) {
116: switch (poscomp(ep->focus, y, x)) {
117:
118: case BEFORE:
119: i = ichild(ep->focus);
120: n = tree(parent(ep->focus)); /* Parent's !!! */
121: rp = noderepr(n);
122: if (Fw_positive(rp[i-1])) {
123: s_up(ep);
124: ep->s1 = ep->s2 = 2*i - 1;
125: ep->mode = SUBSET;
126: }
127: else if (left(&ep->focus))
128: ep->mode = ATEND;
129: else
130: ep->mode = ATBEGIN;
131: return Yes;
132:
133: case INSIDE:
134: n = tree(ep->focus);
135: if (nchildren(n) >= 1 && Type(firstchild(n)) != Tex) {
136: s_down(ep);
137: continue;
138: }
139: ep->mode = WHOLE;
140: return Yes;
141:
142: case BEYOND:
143: if (rite(&ep->focus))
144: continue;
145: n = tree(parent(ep->focus)); /* Parent's !!! */
146: rp = noderepr(n);
147: i = ichild(ep->focus);
148: if (Fw_positive(rp[i])) {
149: s_up(ep);
150: ep->s1 = ep->s2 = 2*i + 1;
151: ep->mode = SUBSET;
152: }
153: else
154: ep->mode = ATEND;
155: return Yes;
156:
157: default:
158: Abort();
159: /* NOTREACHED */
160:
161: }
162: }
163: }
164:
165:
166: /*
167: * Deliver relative position of (y, x) with respect to focus p:
168: * BEFORE: (y, x) precedes focus;
169: * INSIDE: (y, x) contained in focus;
170: * EAFTER: (y, x) follows focus.
171:
172: */
173:
174: Hidden int
175: poscomp(p, y, x)
176: register path p;
177: register int y;
178: register int x;
179: {
180: register int ly;
181: register int lx;
182: register int w;
183: register string *rp;
184: register node n;
185:
186: ly = Ycoord(p);
187: lx = Xcoord(p);
188: if (y < ly || y == ly && (lx < 0 || x < lx))
189: return BEFORE;
190: n = tree(p);
191: w = width(n);
192: if (w < 0) {
193: if (y == ly) { /* Hack for position beyond end of previous line */
194: rp = noderepr(n);
195: if (Fw_negative(rp[0]))
196: return BEFORE;
197: }
198: ly += -w;
199: lx = -1;
200: }
201: else {
202: if (lx >= 0)
203: lx += w;
204: }
205: if (y < ly || y == ly && (lx < 0 || x < lx))
206: return INSIDE;
207: return BEYOND;
208: }
209:
210:
211: /*
212: * Position focus exactly at character indicated by (y, x) if possible.
213: * If this is the start of something larger, position focus at largest
214: * object starting here.
215: */
216:
217: Visible Procedure
218: gotofix(ep, y, x)
219: environ *ep;
220: int y;
221: int x;
222: {
223: int fx;
224: int fy;
225: int len;
226: string repr;
227:
228: switch (ep->mode) {
229:
230: case ATBEGIN:
231: case ATEND:
232: return; /* No change; the mouse pointed in the margin. */
233:
234: case SUBSET:
235: if (ep->s1 > 1) {
236: fx = Xcoord(ep->focus);
237: fy = Ycoord(ep->focus);
238: len = focoffset(ep);
239: if (len < 0 || fy != y)
240: return;
241: if ((ep->s1&1) && fx + len >= x-1) {
242: repr = noderepr(tree(ep->focus))[ep->s1/2];
243: if ((repr && repr[0] == ' ') != (fx + len == x))
244: return;
245: }
246: else if (fx + len == x)
247: return;
248: }
249: ep->mode = WHOLE;
250: /* Fall through */
251: case WHOLE:
252: fx = Xcoord(ep->focus);
253: fy = Ycoord(ep->focus);
254: if (y != fy)
255: return;
256: if (x <= fx ) {
257: for (;;) {
258: if (ichild(ep->focus) > 1)
259: break;
260: if (!up(&ep->focus))
261: break;
262: repr = noderepr(tree(ep->focus))[0];
263: if (!Fw_zero(repr)) {
264: s_down(ep);
265: break;
266: }
267: higher(ep);
268: }
269: if (issublist(symbol(tree(ep->focus))))
270: fixsublist(ep);
271: return;
272: }
273: fixfocus(ep, x - fx);
274: ritevhole(ep);
275: switch(ep->mode) {
276: case VHOLE:
277: len = width(tree(ep->focus));
278: break;
279: case FHOLE:
280: len = fwidth(noderepr(tree(ep->focus))[ep->s1/2]);
281: break;
282: default:
283: return;
284: }
285: if (ep->s2 < len) {
286: ep->mode = SUBRANGE;
287: ep->s3 = ep->s2;
288: }
289: return;
290:
291: default:
292: Abort();
293: }
294: }
295:
296:
297: /*
298: * Refinement for gotoyx -- don't show right sublist of something.
299: */
300:
301: Hidden Procedure
302: fixsublist(ep)
303: environ *ep;
304: {
305: path pa = parent(ep->focus);
306: node n;
307:
308: if (!pa)
309: return;
310: n = tree(pa);
311: if (nchildren(n) > ichild(ep->focus))
312: return;
313: if (samelevel(symbol(n), symbol(tree(ep->focus)))) {
314: ep->mode = SUBLIST;
315: ep->s3 = 1;
316: }
317: }
Defined functions
Defined variables
rcsid
defined in line
2;
never used
Defined macros