|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: static char rcsid[] = "$Header: inse.c,v 2.4 85/02/14 13:27:09 timo Exp $";
3:
4: /*
5: * Subroutines (refinements) for ins_string() (see que2.c).
6: */
7:
8: #include "b.h"
9: #include "feat.h"
10: #include "bobj.h"
11: #include "node.h"
12: #include "gram.h"
13: #include "supr.h"
14: #include "tabl.h"
15:
16: #include <ctype.h>
17:
18:
19: /*
20: * Try to insert the character c in the focus *pp.
21: */
22:
23: Visible bool
24: insguess(pp, c, ep)
25: path *pp;
26: char c;
27: environ *ep;
28: {
29: path pa = parent(*pp);
30: node n;
31: int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
32: int ich = ichild(*pp);
33: struct classinfo *ci = table[sympa].r_class[ich-1];
34: classptr cp;
35: string *rp;
36: int code = Code(c);
37: int sym;
38: char buf[2];
39:
40: #ifdef USERSUGG
41: if (isinclass(Suggestion, ci)) {
42: if (setsugg(pp, c, ep))
43: return Yes;
44: }
45: #endif USERSUGG
46: for (cp = ci->c_insert; *cp; cp += 2) {
47: if (cp[0] == code)
48: break;
49: }
50: if (!*cp)
51: return No;
52: sym = cp[1];
53: if (sym >= LEXICAL) {
54: buf[0] = c;
55: buf[1] = 0;
56: replace(pp, (node) mk_text(buf));
57: ep->mode = VHOLE;
58: ep->s1 = 2*ich;
59: ep->s2 = 1;
60: return Yes;
61: }
62: Assert(sym < TABLEN);
63: rp = table[sym].r_repr;
64: n = table[sym].r_node;
65: if (Fw_zero(rp[0])) {
66: buf[0] = c;
67: buf[1] = 0;
68: setchild(&n, 1, (node) mk_text(buf));
69: replace(pp, n);
70: ep->mode = VHOLE;
71: ep->s1 = 2;
72: ep->s2 = 1;
73: return Yes;
74: }
75: replace(pp, n);
76: if (c == '\n' || c == '\r') {
77: ep->mode = SUBSET;
78: ep->s1 = ep->s2 = 2;
79: }
80: else {
81: ep->mode = FHOLE;
82: ep->s1 = 1;
83: ep->s2 = 1;
84: }
85: return Yes;
86: }
87:
88:
89: /*
90: * Test whether character `c' may be inserted in position `s2' in
91: * child `ich' of node `n'; that child must be a Text.
92: */
93:
94: Visible bool
95: mayinsert(n, ich, s2, c)
96: node n;
97: int ich;
98: int s2;
99: register char c;
100: {
101: int sympa = symbol(n);
102: struct classinfo *ci;
103: register classptr cp;
104: register value v = (value) child(n, ich);
105: register char c1;
106: bool maycontinue();
107: bool maystart();
108: register bool (*fun1)() = s2 > 0 ? maystart : maycontinue;
109: register bool (*fun)() = s2 > 0 ? maycontinue : maystart;
110:
111: Assert(v && v->type == Tex);
112: Assert(sympa > 0 && sympa < TABLEN);
113: ci = table[sympa].r_class[ich-1];
114: Assert(ci && ci->c_class);
115: c1 = Str(v)[0];
116: for (cp = ci->c_class; *cp; ++cp) {
117: if (*cp >= LEXICAL && (*fun1)(c1, *cp)) {
118: if ((*fun)(c, *cp))
119: return Yes;
120: }
121: }
122: return No;
123: }
124:
125:
126: /*
127: * Change a Fixed into a Variable node, given a string pointer variable
128: * which contains the next characters to be inserted.
129: * If the change is not appropriate, No is returned.
130: * Otherwise, as many (though maybe zero) characters from the string
131: * as possible will have been incorporated in the string node.
132: */
133:
134: Visible bool
135: soften(ep, pstr, alt_c)
136: environ *ep;
137: string *pstr;
138: int alt_c;
139: {
140: path pa = parent(ep->focus);
141: node n;
142: int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
143: struct classinfo *ci;
144: register classptr cp;
145: register int code;
146: string repr;
147: register struct table *tp;
148: char buf[1024];
149:
150: if (ep->mode == VHOLE && (ep->s1&1))
151: ep->mode = FHOLE;
152: if (ep->mode != FHOLE || ep->s1 != 1 || ep->s2 <= 0 || !issuggestion(ep))
153: return No;
154: n = tree(ep->focus);
155: repr = noderepr(n)[0];
156: if (!repr || !isupper(repr[0]))
157: return No;
158: code = Code(repr[0]);
159: ci = table[sympa].r_class[ichild(ep->focus) - 1];
160: n = Nnil;
161: for (cp = ci->c_insert; *cp; cp += 2) {
162: if (cp[0] != code)
163: continue;
164: if (cp[1] >= TABLEN)
165: continue;
166: tp = &table[cp[1]];
167: if (Fw_zero(tp->r_repr[0])) {
168: Assert(tp->r_class[0]->c_class[0] >= LEXICAL);
169: n = tp->r_node;
170: break;
171: }
172: }
173: if (!n)
174: return No;
175: strncpy(buf, repr, ep->s2);
176: buf[ep->s2] = 0;
177: setchild(&n, 1, (node) mk_text(buf));
178: if (!mayinsert(n, 1, ep->s2, repr[ep->s2])) {
179: if (!**pstr || !mayinsert(n, 1, ep->s2, **pstr)
180: && (!alt_c || !mayinsert(n, 1, ep->s2, alt_c))) {
181: noderelease(n); /* Don't forget! */
182: return No;
183: }
184: }
185: if (**pstr && mayinsert(n, 1, ep->s2, **pstr)) {
186: do {
187: buf[ep->s2] = **pstr;
188: ++*pstr;
189: ++ep->s2;
190: } while (ep->s2 < sizeof buf - 1 && **pstr
191: && mayinsert(n, 1, ep->s2, **pstr));
192: buf[ep->s2] = 0;
193: setchild(&n, 1, (node) mk_text(buf));
194: }
195: replace(&ep->focus, n);
196: ep->mode = VHOLE;
197: ep->s1 = 2;
198: return Yes;
199: }
200:
201:
202: /*
203: * Renew suggestion, or advance in old suggestion.
204: * Return Yes if *pstr has been advanced.
205: */
206:
207: Visible bool
208: resuggest(ep, pstr, alt_c)
209: environ *ep;
210: string *pstr;
211: int alt_c;
212: {
213: struct table *tp;
214: struct classinfo *ci;
215: classptr cp;
216: path pa;
217: node nn;
218: node n = tree(ep->focus);
219: register string *oldrp = noderepr(n);
220: register int ich = ep->s1/2;
221: register string str = oldrp[ich];
222: int oldsym = symbol(n);
223: int childsym[MAXCHILD];
224: string *newrp;
225: int sympa;
226: register int sym;
227: int symfound = -1;
228: register int i;
229: int code;
230: char buf[15]; /* Should be sufficient for all fixed texts */
231: bool ok;
232: bool anyok = No;
233:
234: if (!str || !**pstr || !issuggestion(ep))
235: return No;
236: /***** Change this if commands can be prefixes of others! *****/
237: /***** Well, they can!
238: if (!c)
239: return No;
240: *****/
241: if (ich > 0 && ifmatch(ep, pstr, str, alt_c))
242: /* Shortcut: sec. keyword, exact match will do just fine */
243: return Yes;
244: if (ep->s2 <= 0 || Fw_zero(oldrp[0]))
245: return No;
246: if (**pstr != ' ' && !isupper(**pstr)
247: && !alt_c && **pstr != '"' && **pstr != '\'')
248: /* Shortcut: not a keyword, must match exactly */
249: return ifmatch(ep, pstr, str, alt_c);
250: for (i = 0; i < ich; ++i) { /* Preset some stuff for main loop */
251: if (!oldrp[i])
252: oldrp[i] = "";
253: childsym[i] = symbol(child(n, i+1));
254: }
255: Assert(ep->s2 + 1 < sizeof buf);
256: strcpy(buf, oldrp[ich]);
257: buf[ep->s2] = alt_c ? alt_c : **pstr;
258: buf[ep->s2 + 1] = 0;
259: pa = parent(ep->focus);
260: sympa = pa ? symbol(tree(pa)) : Rootsymbol;
261: ci = table[sympa].r_class[ichild(ep->focus) - 1];
262: code = Code(oldrp[0][0]);
263:
264: for (cp = ci->c_insert; *cp; cp += 2) {
265: if (cp[0] != code)
266: continue;
267: sym = cp[1];
268: if (sym >= TABLEN)
269: continue;
270: if (sym == oldsym) {
271: anyok = Yes;
272: continue;
273: }
274: tp = &table[sym];
275: newrp = tp->r_repr;
276: ok = Yes;
277: for (i = 0; i < ich; ++i) {
278: str = newrp[i];
279: if (!str)
280: str = "";
281: if (!Strequ(str, oldrp[i])
282: || childsym[i] != Optional && childsym[i] != Hole
283: && !isinclass(childsym[i], tp->r_class[i])) {
284: ok = No;
285: break;
286: }
287: }
288: if (!ok)
289: continue;
290: str = newrp[i];
291: if (!str || !Strnequ(str, buf, ep->s2+1))
292: continue;
293: if (anyok) {
294: if (Strequ(str, oldrp[ich]))
295: continue; /* Same as it was: no new suggestion */
296: symfound = sym;
297: break;
298: }
299: else if (symfound < 0 && !Strequ(str, oldrp[ich]))
300: symfound = sym;
301: }
302:
303: if (symfound < 0)
304: return ifmatch(ep, pstr, oldrp[ich], alt_c);
305: nn = table[symfound].r_node;
306: for (i = 1; i <= ich; ++i) { /* Copy children to the left of the focus */
307: sym = symbol(child(n, i));
308: if (sym == Optional || sym == Hole)
309: continue;
310: setchild(&nn, i, nodecopy(child(n, i)));
311: }
312: replace(&ep->focus, nn);
313: str = newrp[ich];
314: do { /* Find easy continuation */
315: ++ep->s2;
316: ++*pstr;
317: } while (**pstr && **pstr == str[ep->s2]);
318: return Yes;
319: }
320:
321:
322: /*
323: * Refinement for resuggest(): see if there is a match, and if so, find
324: * longest match.
325: */
326:
327: Hidden bool
328: ifmatch(ep, pstr, str, alt_c)
329: register environ *ep;
330: register string *pstr;
331: register string str;
332: register int alt_c;
333: {
334: register int c = str[ep->s2];
335:
336: if (c != **pstr && (!alt_c || c != alt_c))
337: return No;
338: do {
339: ++ep->s2;
340: ++*pstr;
341: } while (**pstr && **pstr == str[ep->s2]);
342: return Yes;
343: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.