1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
   2: static char rcsid[] = "$Header: que2.c,v 2.3 84/07/23 13:02:38 guido Exp $";
   3: 
   4: /*
   5:  * B editor -- Manipulate queues of nodes, higher levels.
   6:  */
   7: 
   8: #include <ctype.h>
   9: 
  10: #include "b.h"
  11: #include "feat.h"
  12: #include "bobj.h"
  13: #include "node.h"
  14: #include "supr.h"
  15: #include "queu.h"
  16: #include "gram.h"
  17: #include "tabl.h"
  18: 
  19: 
  20: extern bool lefttorite;
  21:     /* Set by edit() to signal we parse purely left-to-right */
  22: extern bool dflag; /* Debug mode even if NDEBUG on */
  23: 
  24: 
  25: /*
  26:  * Insert a queue of nodes at the focus
  27:  * (which had better be some kind of a hole).
  28:  * The nodes may also be a text, in which case the individual characters
  29:  * are inserted.
  30:  * Extensive changes to the parse tree may occur, and the node may be
  31:  * broken up in its constituent parts (texts and other nodes) which
  32:  * are then inserted individually.
  33:  */
  34: 
  35: Visible bool
  36: ins_queue(ep, pq, pq2)
  37:     register environ *ep;
  38:     register queue *pq;
  39:     register queue *pq2;
  40: {
  41:     register bool ok = Yes;
  42:     register node n;
  43:     register queue oldq2;
  44:     environ saveenv;
  45:     int oldindentation = focindent(ep);
  46:     int indentation = oldindentation;
  47: 
  48:     leftvhole(ep);
  49:     while (ok && !emptyqueue(*pq)) {
  50:         n = queuebehead(pq);
  51:         if (Type(n) == Tex) {
  52:             ok = ins_string(ep, Str((value) n), pq2, 0);
  53:             switch (Str((value) n)[Length((value) n) - 1]) { /* Last char */
  54:             case '\t':
  55:                 ++indentation;
  56:                 break;
  57:             case '\b':
  58:                 --indentation;
  59:                 break;
  60:             case '\n':
  61:                 while (focindent(ep) > indentation) {
  62:                     if (!ins_newline(ep))
  63:                         break;
  64:                 }
  65:                 break;
  66:             }
  67:         }
  68:         else {
  69:             Ecopy(*ep, saveenv);
  70:             oldq2 = qcopy(*pq2);
  71:             if (!ins_node(&saveenv, n, pq2)) {
  72:                 Erelease(saveenv);
  73:                 qrelease(*pq2);
  74:                 *pq2 = oldq2;
  75:                 if (symbol(n) == Hole)
  76:                     ok = ins_string(ep, "?", pq2, 0);
  77:                 else
  78:                     splitnode(n, pq);
  79:             }
  80:             else {
  81:                 Erelease(*ep);
  82:                 Emove(saveenv, *ep);
  83:                 qrelease(oldq2);
  84:             }
  85:         }
  86:         noderelease(n);
  87:     }
  88:     if (!ok)
  89:         qshow(*pq, "ins_queue");
  90:     qrelease(*pq);
  91:     for (indentation = focindent(ep);
  92:         indentation > oldindentation; --indentation)
  93:         stringtoqueue("\b", pq2); /* Pass on indentation to outer level */
  94:     return ok;
  95: }
  96: 
  97: 
  98: /*
  99:  * Subroutine to insert a queue to the right of the focus
 100:  * without affecting the focus position.
 101:  */
 102: 
 103: Visible bool
 104: app_queue(ep, pq)
 105:     environ *ep;
 106:     queue *pq;
 107: {
 108:     int where;
 109:     static int markbit = 1; /* To properly handle recursive calls */
 110: 
 111:     if (emptyqueue(*pq))
 112:         return Yes;
 113:     where = focoffset(ep);
 114:     markbit <<= 1;
 115:     markpath(&ep->focus, markbit);
 116:     if (!ins_queue(ep, pq, pq)) {
 117:         markbit >>= 1;
 118:         return No;
 119:     }
 120:     firstmarked(&ep->focus, markbit) || Abort();
 121:     unmkpath(&ep->focus, markbit);
 122:     markbit >>= 1;
 123:     ep->spflag = No;
 124:     fixfocus(ep, where);
 125:     return Yes;
 126: }
 127: 
 128: 
 129: /*
 130:  * Advance to next thing after current position.
 131:  */
 132: 
 133: Visible bool
 134: move_on(ep)
 135:     register environ *ep;
 136: {
 137:     register node n;
 138:     register string *rp;
 139:     register int sym;
 140:     register int ich = ichild(ep->focus);
 141: 
 142:     if (!up(&ep->focus))
 143:         return No;
 144:     higher(ep);
 145:     n = tree(ep->focus);
 146:     rp = noderepr(n);
 147:     if (Fw_positive(rp[ich])) {
 148:         ep->mode = FHOLE;
 149:         ep->s1 = 2*ich + 1;
 150:         ep->s2 = 0;
 151:         if (ep->spflag) {
 152:             ep->spflag = No;
 153:             if (rp[ich][0] == ' ') {
 154:                 ++ep->s2;
 155:                 if (fwidth(rp[ich]) > 1)
 156:                     return Yes;
 157:             }
 158:             else
 159:                 return Yes;
 160:         }
 161:         else
 162:             return Yes;
 163:     }
 164:     if (ich < nchildren(n)) {
 165:         s_downi(ep, ich+1);
 166:         sym = symbol(tree(ep->focus));
 167:         if (sym == Hole || sym == Optional)
 168:             ep->mode = WHOLE;
 169:         else
 170:             ep->mode = ATBEGIN;
 171:         return Yes;
 172:     }
 173:     ep->mode = ATEND;
 174:     return Yes;
 175: }
 176: 
 177: 
 178: /*
 179:  * Like move_on but moves through fixed texts, skipping only spaces
 180:  * and empty strings.
 181:  * <<<<< This code is a dinosaur and should be revised. >>>>>
 182:  */
 183: 
 184: Visible bool
 185: fix_move(ep)
 186:     register environ *ep;
 187: {
 188:     register int ich;
 189:     register int i;
 190:     register string *rp;
 191:     register string cp;
 192: 
 193:     Assert(ep->mode == FHOLE);
 194: 
 195:     ich = ep->s1/2;
 196:     rp = noderepr(tree(ep->focus));
 197:     cp = rp[ich];
 198:     if (cp) {
 199:         i = ep->s2;
 200:         Assert(i <= Fwidth(cp));
 201:         if (cp[i] == ' ') {
 202:             do {
 203:                 ++i;
 204:             } while (cp[i] == ' ');
 205:         }
 206:         if (cp[i] == '\b' || cp[i] == '\t') {
 207:             ++i;
 208:             Assert(!cp[i]);
 209:         }
 210:         else if (cp[i]) {
 211:             if (i == ep->s2)
 212:                 return No;
 213:             ep->s2 = i;
 214:             return Yes;
 215:         }
 216:     }
 217: 
 218:     if (ich >= nchildren(tree(ep->focus)))
 219:         ep->mode = ATEND;
 220:     else {
 221:         s_downi(ep, ich+1);
 222:         if (symbol(tree(ep->focus)) == Hole
 223:             || symbol(tree(ep->focus)) == Optional)
 224:             ep->mode = WHOLE;
 225:         else
 226:             ep->mode = ATBEGIN;
 227:     }
 228:     return Yes;
 229: }
 230: 
 231: 
 232: /*
 233:  * Insert a node in the parse tree.
 234:  */
 235: 
 236: Hidden bool
 237: ins_node(ep, n, pq)
 238:     register environ *ep;
 239:     register node n;
 240:     register queue *pq;
 241: {
 242:     register int sym;
 243:     register node nn;
 244:     register markbits x;
 245:     string *rp;
 246: 
 247:     if (symbol(n) == Optional)
 248:         return Yes;
 249: 
 250:     for (;;) {
 251:         switch (ep->mode) {
 252: 
 253:         case FHOLE:
 254:             if (ep->s2 < lenitem(ep) || !fix_move(ep))
 255:                 return No;
 256:             continue;
 257: 
 258:         case VHOLE:
 259:             if (ep->s2 < lenitem(ep) || !move_on(ep))
 260:                 return No;
 261:             continue;
 262: 
 263:         case ATBEGIN:
 264:             sym = symbol(tree(ep->focus));
 265:             if (sym == Optional || sym == Hole) {
 266:                 ep->mode = WHOLE;
 267:                 continue;
 268:             }
 269:             x = marks(tree(ep->focus));
 270:             if (joinnodes(&ep->focus, n, tree(ep->focus), No)) {
 271:                 if (x) {
 272:                     s_downi(ep, 2);
 273:                     markpath(&ep->focus, x);
 274:                     s_up(ep);
 275:                 }
 276:                 s_down(ep);
 277:                 ep->mode = ATEND;
 278:                 leftvhole(ep);
 279:                 return Yes;
 280:             }
 281:             nn = tree(ep->focus);
 282:             rp = noderepr(nn);
 283:             if (nchildren(nn) >= 1 && Fw_zero(rp[0])) {
 284:                 sym = symbol(firstchild(nn));
 285:                 if (sym == Hole || sym == Optional) {
 286:                     s_down(ep);
 287:                     if (fitnode(&ep->focus, n)) {
 288:                         ep->mode = ATEND;
 289:                         leftvhole(ep);
 290:                         return Yes;
 291:                     }
 292:                     s_up(ep);
 293:                 }
 294:             }
 295:             nn = nodecopy(nn);
 296:             if (!fitnode(&ep->focus, n)) {
 297:                 addtoqueue(pq, nn);
 298:                 noderelease(nn);
 299:                 delfocus(&ep->focus);
 300:                 ep->mode = WHOLE;
 301:                 continue;
 302:             }
 303:             if (downrite(&ep->focus)) {
 304:                 if (Type(tree(ep->focus)) != Tex) {
 305:                     sym = symbol(tree(ep->focus));
 306:                     if (sym == Hole || sym == Optional) {
 307:                         if (fitnode(&ep->focus, nn)) {
 308:                             noderelease(nn);
 309:                             nn = Nnil;
 310:                         }
 311:                     }
 312:                 }
 313:                 else
 314:                     up(&ep->focus);
 315:             }
 316:             if (nn) {
 317:                 addtoqueue(pq, nn);
 318:                 noderelease(nn);
 319:             }
 320:             ep->mode = ATEND;
 321:             leftvhole(ep);
 322:             return Yes;
 323: 
 324:         case WHOLE:
 325:             sym = symbol(tree(ep->focus));
 326:             Assert(sym == Optional || sym == Hole);
 327:             do {
 328:                 higher(ep); /* Only for second time around */
 329:                 if (fitnode(&ep->focus, n)) {
 330:                     ep->mode = ATEND;
 331:                     leftvhole(ep);
 332:                     return Yes;
 333:                 }
 334:             } while (resttoqueue(&ep->focus, pq));
 335:             ep->mode = ATEND;
 336:             /* Fall through */
 337:         case ATEND:
 338:             do {
 339:                 higher(ep); /* Only for second time around */
 340:                 if (joinnodes(&ep->focus, tree(ep->focus), n, ep->spflag)) {
 341:                     ep->spflag = No;
 342:                     leftvhole(ep);
 343:                     return Yes;
 344:                 }
 345:             } while (resttoqueue(&ep->focus, pq)
 346:                 || move_on(ep) && ep->mode == ATEND);
 347:             return No;
 348: 
 349:         default:
 350:             return No;
 351: 
 352:         }
 353:     }
 354: }
 355: 
 356: 
 357: /*
 358:  * Insert a string in the parse tree.
 359:  */
 360: 
 361: #define NEXT (++str, alt_c = 0)
 362: 
 363: Visible bool
 364: ins_string(ep, str, pq, alt_c)
 365:     register environ *ep;
 366:     /*auto*/ string str;
 367:     register queue *pq;
 368:     int alt_c;
 369: {
 370:     register node nn;
 371:     auto value v;
 372:     char buf[1024];
 373:     register string repr;
 374:     string oldstr;
 375:     register int sym;
 376:     register int len;
 377:     bool interactive = alt_c != 0;
 378: 
 379:     if (alt_c < 0)
 380:         alt_c = 0;
 381:     while (*str) {
 382:         switch (*str) {
 383: 
 384:         case '\n':
 385:             if (!ins_newline(ep))
 386:                 return No;
 387:             /* Fall through */
 388:         case '\t':
 389:         case '\b':
 390:             NEXT;
 391:             continue;
 392: 
 393:         }
 394:         switch (ep->mode) {
 395: 
 396:         case ATBEGIN:
 397:             nn = tree(ep->focus);
 398:             if (Type(nn) == Tex) {
 399:                 ep->s1 = 2*ichild(ep->focus);
 400:                 ep->s2 = 0;
 401:                 ep->mode = VHOLE;
 402:                 s_up(ep);
 403:                 continue;
 404:             }
 405:             sym = symbol(nn);
 406:             if (sym != Optional && sym != Hole) {
 407:                 if (fwidth(noderepr(nn)[0]) == 0) {
 408:                     if (down(&ep->focus))
 409:                         break;
 410:                 }
 411:                 addtoqueue(pq, nn);
 412:                 delfocus(&ep->focus);
 413:             }
 414:             ep->mode = WHOLE;
 415:             /* Fall through */
 416:         case WHOLE:
 417:             nn = tree(ep->focus);
 418:             sym = symbol(nn);
 419:             Assert(sym == Hole || sym == Optional);
 420:             while ((len = fitstring(&ep->focus, str, alt_c)) == 0) {
 421:                 if (sym == Optional) {
 422:                     if (!move_on(ep)) {
 423:                         if (*str == ' ')
 424:                             NEXT;
 425:                         else
 426:                             return No;
 427:                     }
 428:                     break;
 429:                 }
 430:                 if (!interactive && *str == '?') {
 431:                     NEXT;
 432:                     ep->mode = ATEND;
 433:                     break;
 434:                 }
 435:                 if (resttoqueue(&ep->focus, pq))
 436:                     higher(ep);
 437:                 else if (spacefix(ep))
 438:                     break;
 439:                 else if (*str == ' ') {
 440:                     NEXT;
 441:                     break;
 442:                 }
 443:                 else if (interactive)
 444:                     return No;
 445:                 else {
 446:                     ep->mode = ATEND;
 447:                     break;
 448:                 }
 449:             }
 450:             if (len > 0) {
 451:                 str += len;
 452:                 alt_c = 0;
 453:                 fixfocus(ep, len);
 454:             }
 455:             break;
 456: 
 457:         case ATEND:
 458:             if (add_string(ep, &str, alt_c)) {
 459:                 alt_c = 0;
 460:                 break;
 461:             }
 462:             len = joinstring(&ep->focus, str, ep->spflag,
 463:                 alt_c ? alt_c : interactive ? -1 : 0, Yes);
 464:             if (len > 0) {
 465:                 s_downi(ep, 2);
 466:                 ep->spflag = No;
 467:                 fixfocus(ep, len);
 468:             }
 469:             else {
 470:                 if (resttoqueue(&ep->focus, pq)) {
 471:                     higher(ep);
 472:                     break;
 473:                 }
 474:                 if (move_on(ep))
 475:                     break;
 476:                 if (*str == ' ') {
 477:                     NEXT;
 478:                     break;
 479:                 }
 480:                 return No;
 481:             }
 482:             str += len;
 483:             alt_c = 0;
 484:             break;
 485: 
 486:         case FHOLE:
 487:             nn = tree(ep->focus);
 488:             repr = noderepr(nn)[ep->s1/2];
 489:             if (ep->s2 >= fwidth(repr)
 490:                 && (ep->s2 <= 0 || ep->spflag || !isalpha(repr[0])
 491:                     || repr[ep->s2-1] == ' ')) { /* At end */
 492:                 if (ep->s1/2 < nchildren(nn)) {
 493:                     s_downi(ep, ep->s1/2 + 1);
 494:                     ep->mode = ATBEGIN; /* Of next child */
 495:                 }
 496:                 else
 497:                     ep->mode = ATEND;
 498:                 break;
 499:             }
 500:             if ((*str == ':' || *str == ' ') && *str == repr[ep->s2]) {
 501:                 /*****
 502: 				 * Quick hack for insertion of test-suites and refinements:
 503: 				 *****/
 504:                 ++ep->s2;
 505:                 NEXT;
 506:                 continue;
 507:             }
 508:             if (!lefttorite)
 509:                 nosuggtoqueue(ep, pq);
 510:             oldstr = str;
 511:             if (resuggest(ep, &str, alt_c) || soften(ep, &str, alt_c)) {
 512:                 if (str > oldstr)
 513:                     alt_c = 0;
 514:                 continue;
 515:             }
 516:             if (fix_move(ep))
 517:                 continue;
 518:             return No;
 519: 
 520:         case VHOLE:
 521:             Assert(!(ep->s1&1));
 522:             nn = tree(ep->focus);
 523: #ifdef USERSUGG
 524:             if (symbol(nn) == Suggestion) {
 525:                 if (newsugg(ep, &str, alt_c))
 526:                     alt_c = 0;
 527:                 else
 528:                     killsugg(ep);
 529:                 continue;
 530:             }
 531: #endif USERSUGG
 532:             s_downi(ep, ep->s1/2);
 533:             v = copy((value) tree(ep->focus));
 534:             len = 0;
 535:             if (!ep->spflag) {
 536:                 for (; len < sizeof buf - 1 && str[len]
 537:                         && mayinsert(nn, ep->s1/2, !!(ep->s2 + len),
 538:                             str[len]);
 539:                     ++len) {
 540:                     buf[len] = str[len];
 541:                 }
 542:                 if (len <= 0 && alt_c
 543:                     && mayinsert(nn, ep->s1/2, !!(ep->s2 + len), alt_c)) {
 544:                     buf[0] = alt_c;
 545:                     len = 1;
 546:                 }
 547:             }
 548:             if (len > 0) { /* Effectuate change */
 549:                 str += len;
 550:                 alt_c = 0;
 551:                 Assert(Type(v) == Tex);
 552:                 buf[len] = 0;
 553:                 putintrim(&v, ep->s2, Length(v) - ep->s2, buf);
 554:                 replace(&ep->focus, (node) v);
 555:                 s_up(ep);
 556:                 ep->spflag = No;
 557:                 ep->s2 += len;
 558:             }
 559:             else { /* Nothing inserted */
 560:                 if (ep->s2 == 0) { /* Whole string rejected */
 561:                     addtoqueue(pq, (node)v);
 562:                     release(v);
 563:                     s_up(ep);
 564:                     delfocus(&ep->focus);
 565:                     ep->mode = WHOLE;
 566:                     break;
 567:                 }
 568:                 if (ep->s2 < Length(v)) {
 569:                     addstringtoqueue(pq, Str(v) + ep->s2);
 570:                     putintrim(&v, ep->s2, 0, "");
 571:                     replace(&ep->focus, (node) v);
 572:                 }
 573:                 else
 574:                     release(v);
 575:                 move_on(ep) || Abort(); /* ==> up, cancelling s_downi! */
 576:             }
 577:             break;
 578: 
 579:         default:
 580:             Abort();
 581: 
 582:         }
 583:     }
 584: 
 585:     return Yes;
 586: }
 587: 
 588: 
 589: /*
 590:  * See if two nodes can be joined in a hole.
 591:  * 'Spflag' indicates whether a space must be present between the nodes
 592:  * (required or forbidden).
 593:  * Either of n1, n2 may actually be the current contents of the hole.
 594:  */
 595: 
 596: Hidden bool
 597: joinnodes(pp, n1, n2, spflag)
 598:     path *pp;
 599:     node n1;
 600:     node n2;
 601:     bool spflag;
 602: {
 603:     path pa = parent(*pp);
 604:     int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
 605:     struct table *tp = &table[sympa];
 606:     struct classinfo *ci = tp->r_class[ichild(*pp) - 1];
 607:     classptr cp = ci->c_join;
 608:     int sym1 = symbol(n1);
 609:     int sym2 = symbol(n2);
 610:     int symcp;
 611:     int symfound = -1;
 612: 
 613:     if (!cp)
 614:         return No;
 615:     for (; *cp; cp += 2) {
 616:         if (cp[0] != spflag + 1)
 617:             continue;
 618:         symcp = cp[1];
 619:         tp = &table[symcp];
 620:         if (isinclass(sym1, tp->r_class[0])
 621:             && isinclass(sym2, tp->r_class[1])) {
 622:             symfound = symcp;
 623:             break;
 624:         }
 625:     }
 626: 
 627:     if (symfound < 0)
 628:         return No;
 629:     n1 = nodecopy(n1);
 630:     n2 = nodecopy(n2); /* 'Cause one of them may overlap tree(*pp) */
 631:     replace(pp, table[symfound].r_node);
 632:     down(pp) || Abort();
 633:     replace(pp, n1);
 634:     rite(pp) || Abort();
 635:     replace(pp, n2);
 636:     up(pp) || Abort();
 637:     return Yes;
 638: }
 639: 
 640: 
 641: /*
 642:  * Try to join a node (implicit as tree(*pp)) with some text.
 643:  * That is, try to replace the node by one with it as first child,
 644:  * (some of) the text as second child, and nothing or a space in between.
 645:  *
 646:  * 'Spflag' indicates whether a space is desirable between the nodes
 647:  * (but if No it is only used as advice).
 648:  *
 649:  * Returns the number of characters consumed from str.
 650:  */
 651: 
 652: Visible int
 653: joinstring(pp, str, spflag, alt_c, mayindent)
 654:     path *pp;
 655:     register string str;
 656:     register bool spflag;
 657:     int alt_c;
 658:     bool mayindent;
 659: {
 660:     register struct table *tp;
 661:     path pa = parent(*pp);
 662:     node n1;
 663:     struct classinfo *ci;
 664:     register classptr cp;
 665:     int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
 666:     register int sym1;
 667:     register int symcp;
 668:     int symfound;
 669:     int len;
 670:     char buf[2];
 671:     bool interactive = alt_c != 0;
 672: 
 673:     if (alt_c < 0)
 674:         alt_c = 0;
 675:     ci = table[sympa].r_class[ichild(*pp) - 1];
 676:     Assert(ci);
 677:     cp = ci->c_join;
 678:     if (!cp)
 679:         return 0;
 680: 
 681:     n1 = tree(*pp);
 682:     sym1 = symbol(n1);
 683:     symfound = -1;
 684:     for (; *cp; cp += 2) {
 685:         if (cp[0] < spflag + 1)
 686:             continue;
 687:         symcp = cp[1];
 688:         tp = &table[symcp];
 689:         if (!mayindent && tp->r_repr[1] && index(tp->r_repr[1], '\t'))
 690:             continue;
 691:         if (isinclass(sym1, tp->r_class[0])
 692:             && ((canfitchar(str[0], tp->r_class[1]))
 693:                 || str[0] == '?' && !interactive)) {
 694:             if (cp[0] == spflag + 1) {
 695:                 symfound = symcp;
 696:                 break;
 697:             }
 698:             if (symfound < 0)
 699:                 symfound = symcp;
 700:         }
 701:     }
 702: 
 703:     if (symfound < 0) { /* 1-level recursion */
 704:         if (!alt_c)
 705:             return 0;
 706:         buf[0] = alt_c;
 707:         buf[1] = 0;
 708:         return joinstring(pp, buf, spflag, 0, mayindent);
 709:     }
 710:     n1 = nodecopy(n1); /* 'Cause it overlaps tree(*pp) */
 711:     replace(pp, table[symfound].r_node);
 712:     down(pp) || Abort();
 713:     replace(pp, n1);
 714:     rite(pp) || Abort();
 715:     len = fitstring(pp, str, 0);
 716:     if (len == 0 && str[0] == '?')
 717:         len = 1;
 718:     Assert(len > 0); /* Disagreement between canfitchar and fitstring */
 719:     up(pp) || Abort();
 720:     return len;
 721: }
 722: 
 723: 
 724: /*
 725:  * Similar to joinstring, but now the string must match the delimiter
 726:  * rather than being acceptable as second child.
 727:  * (Interface has changed to resemble resuggest/soften.)
 728:  */
 729: 
 730: Hidden bool
 731: add_string(ep, pstr, alt_c)
 732:     environ *ep;
 733:     string *pstr;
 734:     int alt_c; /* Yet unused */
 735: {
 736:     register struct table *tp;
 737:     path pa = parent(ep->focus);
 738:     node n1;
 739:     struct classinfo *ci;
 740:     register classptr cp;
 741:     int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
 742:     register int sym1;
 743:     register int symcp;
 744:     register int c;
 745: 
 746:     ci = table[sympa].r_class[ichild(ep->focus) - 1];
 747:     Assert(ci);
 748:     cp = ci->c_append;
 749:     if (!cp)
 750:         return No;
 751:     n1 = tree(ep->focus);
 752:     sym1 = symbol(n1);
 753:     c = **pstr;
 754:     for (; *cp; cp += 2) {
 755:         if ((*cp&0177) != c)
 756:             continue;
 757:         symcp = cp[1];
 758:         tp = &table[symcp];
 759:         if (isinclass(sym1, tp->r_class[0]))
 760:             break;
 761:     }
 762:     if (!*cp)
 763:         return No;
 764:     ++*pstr;
 765:     if (c == ' ') {
 766:         ep->spflag = Yes;
 767:         return Yes;
 768:     }
 769:     n1 = nodecopy(n1); /* 'Cause it overlaps tree(ep->focus) */
 770:     replace(&ep->focus, table[symcp].r_node);
 771:     s_down(ep);
 772:     replace(&ep->focus, n1);
 773:     s_up(ep);
 774:     ep->mode = FHOLE;
 775:     ep->s1 = 3;
 776:     ep->s2 = (*cp&0200) ? 2 : 1;
 777:     ep->spflag = No;
 778:     return Yes;
 779: }
 780: 
 781: 
 782: /*
 783:  * See whether a character may start a new node in a hole with given class.
 784:  */
 785: 
 786: Visible bool
 787: canfitchar(c, ci)
 788:     int c;
 789:     struct classinfo *ci;
 790: {
 791:     register classptr cp;
 792:     register int code = Code(c);
 793: 
 794:     Assert(ci);
 795:     cp = ci->c_insert;
 796:     Assert(cp);
 797:     for (; *cp; cp += 2) {
 798:         if (cp[0] == code)
 799:             return Yes;
 800:     }
 801:     return No;
 802: }
 803: 
 804: 
 805: /*
 806:  * Debug routine to print a queue.
 807:  */
 808: 
 809: Visible Procedure
 810: qshow(q, where)
 811:     queue q;
 812:     string where;
 813: {
 814: #ifndef NDEBUG
 815:     node n;
 816:     char buf[256];
 817:     string cp;
 818:     string sp;
 819: 
 820:     sprintf(buf, "%s:", where);
 821:     cp = buf + strlen(buf);
 822:     for (;q; q = q->q_link) {
 823:         n = q->q_data;
 824:         *cp++ = ' ';
 825:         if (Type(n) == Tex) {
 826:             *cp++ = '"';
 827:             for (sp = Str((value) n); *sp; ++sp) {
 828:                 if (isprint(*sp) || *sp == ' ') {
 829:                     *cp++ = *sp;
 830:                     if (*sp == '"')
 831:                         *cp++ = *sp;
 832:                 }
 833:                 else {
 834:                     sprintf(cp, "\\%03o", *sp&0377);
 835:                     cp += 4;
 836:                 }
 837:             }
 838:             *cp++ = '"';
 839:         }
 840:         else {
 841:             strncpy(cp, table[symbol(n)].r_name, 80);
 842:             cp += strlen(cp);
 843:         }
 844:         if (cp >= buf+80) {
 845:             strcpy(buf+76, "...");
 846:             break;
 847:         }
 848:     }
 849:     *cp = 0;
 850:     debug(buf);
 851: #endif NDEBUG
 852: }

Defined functions

add_string defined in line 730; used 1 times
canfitchar defined in line 786; used 1 times
fix_move defined in line 184; used 3 times
ins_node defined in line 236; used 1 times
  • in line 71
ins_queue defined in line 35; used 5 times
joinnodes defined in line 596; used 2 times
joinstring defined in line 652; used 3 times
move_on defined in line 133; used 6 times
qshow defined in line 809; used 1 times
  • in line 89

Defined variables

rcsid defined in line 2; never used

Defined macros

NEXT defined in line 361; used 6 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4123
Valid CSS Valid XHTML 1.0 Strict