|
|
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.