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: }

Defined functions

ifmatch defined in line 327; used 3 times
insguess defined in line 23; used 2 times
resuggest defined in line 207; used 1 times

Defined variables

rcsid defined in line 2; never used
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1262
Valid CSS Valid XHTML 1.0 Strict