|
|
BSD 4.3tahoe
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
static char rcsid[] = "$Header: /var/lib/cvsd/repos/CSRG/43BSDTahoe/new/B/src/bed/inse.c,v 1.1.1.1 2018/04/24 16:12:58 root Exp $";
/*
* Subroutines (refinements) for ins_string() (see que2.c).
*/
#include "b.h"
#include "feat.h"
#include "bobj.h"
#include "node.h"
#include "gram.h"
#include "supr.h"
#include "tabl.h"
#include <ctype.h>
/*
* Try to insert the character c in the focus *pp.
*/
Visible bool
insguess(pp, c, ep)
path *pp;
char c;
environ *ep;
{
path pa = parent(*pp);
node n;
int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
int ich = ichild(*pp);
struct classinfo *ci = table[sympa].r_class[ich-1];
classptr cp;
string *rp;
int code = Code(c);
int sym;
char buf[2];
#ifdef USERSUGG
if (isinclass(Suggestion, ci)) {
if (setsugg(pp, c, ep))
return Yes;
}
#endif USERSUGG
for (cp = ci->c_insert; *cp; cp += 2) {
if (cp[0] == code)
break;
}
if (!*cp)
return No;
sym = cp[1];
if (sym >= LEXICAL) {
buf[0] = c;
buf[1] = 0;
replace(pp, (node) mk_text(buf));
ep->mode = VHOLE;
ep->s1 = 2*ich;
ep->s2 = 1;
return Yes;
}
Assert(sym < TABLEN);
rp = table[sym].r_repr;
n = table[sym].r_node;
if (Fw_zero(rp[0])) {
buf[0] = c;
buf[1] = 0;
setchild(&n, 1, (node) mk_text(buf));
replace(pp, n);
ep->mode = VHOLE;
ep->s1 = 2;
ep->s2 = 1;
return Yes;
}
replace(pp, n);
if (c == '\n' || c == '\r') {
ep->mode = SUBSET;
ep->s1 = ep->s2 = 2;
}
else {
ep->mode = FHOLE;
ep->s1 = 1;
ep->s2 = 1;
}
return Yes;
}
/*
* Test whether character `c' may be inserted in position `s2' in
* child `ich' of node `n'; that child must be a Text.
*/
Visible bool
mayinsert(n, ich, s2, c)
node n;
int ich;
int s2;
register char c;
{
int sympa = symbol(n);
struct classinfo *ci;
register classptr cp;
register value v = (value) child(n, ich);
register char c1;
bool maycontinue();
bool maystart();
register bool (*fun1)() = s2 > 0 ? maystart : maycontinue;
register bool (*fun)() = s2 > 0 ? maycontinue : maystart;
Assert(v && v->type == Tex);
Assert(sympa > 0 && sympa < TABLEN);
ci = table[sympa].r_class[ich-1];
Assert(ci && ci->c_class);
c1 = Str(v)[0];
for (cp = ci->c_class; *cp; ++cp) {
if (*cp >= LEXICAL && (*fun1)(c1, *cp)) {
if ((*fun)(c, *cp))
return Yes;
}
}
return No;
}
/*
* Change a Fixed into a Variable node, given a string pointer variable
* which contains the next characters to be inserted.
* If the change is not appropriate, No is returned.
* Otherwise, as many (though maybe zero) characters from the string
* as possible will have been incorporated in the string node.
*/
Visible bool
soften(ep, pstr, alt_c)
environ *ep;
string *pstr;
int alt_c;
{
path pa = parent(ep->focus);
node n;
int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
struct classinfo *ci;
register classptr cp;
register int code;
string repr;
register struct table *tp;
char buf[1024];
if (ep->mode == VHOLE && (ep->s1&1))
ep->mode = FHOLE;
if (ep->mode != FHOLE || ep->s1 != 1 || ep->s2 <= 0 || !issuggestion(ep))
return No;
n = tree(ep->focus);
repr = noderepr(n)[0];
if (!repr || !isupper(repr[0]))
return No;
code = Code(repr[0]);
ci = table[sympa].r_class[ichild(ep->focus) - 1];
n = Nnil;
for (cp = ci->c_insert; *cp; cp += 2) {
if (cp[0] != code)
continue;
if (cp[1] >= TABLEN)
continue;
tp = &table[cp[1]];
if (Fw_zero(tp->r_repr[0])) {
Assert(tp->r_class[0]->c_class[0] >= LEXICAL);
n = tp->r_node;
break;
}
}
if (!n)
return No;
strncpy(buf, repr, ep->s2);
buf[ep->s2] = 0;
setchild(&n, 1, (node) mk_text(buf));
if (!mayinsert(n, 1, ep->s2, repr[ep->s2])) {
if (!**pstr || !mayinsert(n, 1, ep->s2, **pstr)
&& (!alt_c || !mayinsert(n, 1, ep->s2, alt_c))) {
noderelease(n); /* Don't forget! */
return No;
}
}
if (**pstr && mayinsert(n, 1, ep->s2, **pstr)) {
do {
buf[ep->s2] = **pstr;
++*pstr;
++ep->s2;
} while (ep->s2 < sizeof buf - 1 && **pstr
&& mayinsert(n, 1, ep->s2, **pstr));
buf[ep->s2] = 0;
setchild(&n, 1, (node) mk_text(buf));
}
replace(&ep->focus, n);
ep->mode = VHOLE;
ep->s1 = 2;
return Yes;
}
/*
* Renew suggestion, or advance in old suggestion.
* Return Yes if *pstr has been advanced.
*/
Visible bool
resuggest(ep, pstr, alt_c)
environ *ep;
string *pstr;
int alt_c;
{
struct table *tp;
struct classinfo *ci;
classptr cp;
path pa;
node nn;
node n = tree(ep->focus);
register string *oldrp = noderepr(n);
register int ich = ep->s1/2;
register string str = oldrp[ich];
int oldsym = symbol(n);
int childsym[MAXCHILD];
string *newrp;
int sympa;
register int sym;
int symfound = -1;
register int i;
int code;
char buf[15]; /* Should be sufficient for all fixed texts */
bool ok;
bool anyok = No;
if (!str || !**pstr || !issuggestion(ep))
return No;
/***** Change this if commands can be prefixes of others! *****/
/***** Well, they can!
if (!c)
return No;
*****/
if (ich > 0 && ifmatch(ep, pstr, str, alt_c))
/* Shortcut: sec. keyword, exact match will do just fine */
return Yes;
if (ep->s2 <= 0 || Fw_zero(oldrp[0]))
return No;
if (**pstr != ' ' && !isupper(**pstr)
&& !alt_c && **pstr != '"' && **pstr != '\'')
/* Shortcut: not a keyword, must match exactly */
return ifmatch(ep, pstr, str, alt_c);
for (i = 0; i < ich; ++i) { /* Preset some stuff for main loop */
if (!oldrp[i])
oldrp[i] = "";
childsym[i] = symbol(child(n, i+1));
}
Assert(ep->s2 + 1 < sizeof buf);
strcpy(buf, oldrp[ich]);
buf[ep->s2] = alt_c ? alt_c : **pstr;
buf[ep->s2 + 1] = 0;
pa = parent(ep->focus);
sympa = pa ? symbol(tree(pa)) : Rootsymbol;
ci = table[sympa].r_class[ichild(ep->focus) - 1];
code = Code(oldrp[0][0]);
for (cp = ci->c_insert; *cp; cp += 2) {
if (cp[0] != code)
continue;
sym = cp[1];
if (sym >= TABLEN)
continue;
if (sym == oldsym) {
anyok = Yes;
continue;
}
tp = &table[sym];
newrp = tp->r_repr;
ok = Yes;
for (i = 0; i < ich; ++i) {
str = newrp[i];
if (!str)
str = "";
if (!Strequ(str, oldrp[i])
|| childsym[i] != Optional && childsym[i] != Hole
&& !isinclass(childsym[i], tp->r_class[i])) {
ok = No;
break;
}
}
if (!ok)
continue;
str = newrp[i];
if (!str || !Strnequ(str, buf, ep->s2+1))
continue;
if (anyok) {
if (Strequ(str, oldrp[ich]))
continue; /* Same as it was: no new suggestion */
symfound = sym;
break;
}
else if (symfound < 0 && !Strequ(str, oldrp[ich]))
symfound = sym;
}
if (symfound < 0)
return ifmatch(ep, pstr, oldrp[ich], alt_c);
nn = table[symfound].r_node;
for (i = 1; i <= ich; ++i) { /* Copy children to the left of the focus */
sym = symbol(child(n, i));
if (sym == Optional || sym == Hole)
continue;
setchild(&nn, i, nodecopy(child(n, i)));
}
replace(&ep->focus, nn);
str = newrp[ich];
do { /* Find easy continuation */
++ep->s2;
++*pstr;
} while (**pstr && **pstr == str[ep->s2]);
return Yes;
}
/*
* Refinement for resuggest(): see if there is a match, and if so, find
* longest match.
*/
Hidden bool
ifmatch(ep, pstr, str, alt_c)
register environ *ep;
register string *pstr;
register string str;
register int alt_c;
{
register int c = str[ep->s2];
if (c != **pstr && (!alt_c || c != alt_c))
return No;
do {
++ep->s2;
++*pstr;
} while (**pstr && **pstr == str[ep->s2]);
return Yes;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.