home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / inse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-24  |  7.2 KB  |  344 lines

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