# 2.11BSD#431 - /usr/src/new/PORT/B/src/bed/que1.c

##### Functions

    addstringtoqueue  X
    addtoqueue        X
    fitnode           X
    fitstring         X
    fixfocus          X
    issuggestion      X
    joinqueues        X
    nosuggtoqueue     X
    preptoqueue       X
    querepr           X
    queuebehead       X
    resttoqueue       X
    spacefix          X
    splitnode         X
    stringtoqueue     X
    subsettoqueue     X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
       2: static char rcsid[] = "$Header: que1.c,v 2.4 84/10/26 12:04:28 guido Exp $";
       3:
       4: /*
       5:  * B editor -- Manipulate queues of nodes, lower levels.
       6:  */
       7:
       8: #include "b.h"
       9: #include "feat.h"
      10: #include "bobj.h"
      11: #include "node.h"
      12: #include "supr.h"
      13: #include "queu.h"
      14: #include "gram.h"
      15:
      16: #include <ctype.h>
      17:
      18:
      19: value grab_com();
      20:
      21:
      22: /*
      23:  * Append queue 2 to the end of queue 1.
      24:  */
      25:
      26: Visible Procedure
      27: joinqueues(pq, q)
      28:     register queue *pq;
      29:     register queue q;
      30: {
      31:     if (emptyqueue(q))
      32:         return;
      33:     while (*pq) {
      34:         if (Refcnt(*pq) > 1)
      35:             uniql((value*)pq);
      36:         pq = &(*pq)->q_link;
      37:     }
      38:     *pq = q;
      39: }
      40:
      41:
      42: /*
      43:  * Prepend a node to a queue ("push").
      44:  * Empty strings and Optional holes are silently discarded.
      45:  */
      46:
      47: Visible Procedure
      48: preptoqueue(n, pq)
      49:     node n;
      50:     register queue *pq;
      51: {
      52:     register queue q;
      53:
      54:     if (Type(n) == Tex) {
      55:         int len = Length((value)n);
      56:         if (len == 0)
      57:             return;
      58:         n = nodecopy(n);
      59:     }
      60:     else { /* Avoid Optional holes */
      61:         if (symbol(n) == Optional)
      62:             return;
      63:         n = nodecopy(n);
      64:     }
      65:     q = (queue) grab_com(2);
      66:     q->q_data = n;
      67:     q->q_link = *pq;
      68:     *pq = q;
      69: }
      70:
      71:
      72: /*
      73:  * Append a node to the end of a queue (same extras as preptoqueue).
      74:  */
      75:
      76: Visible Procedure
      77: addtoqueue(pq, n)
      78:     register queue *pq;
      79:     register node n;
      80: {
      81:     auto queue q = Qnil;
      82:
      83:     preptoqueue(n, &q);
      84:     joinqueues(pq, q);
      85: }
      86:
      87:
      88: /*
      89:  * Push a string onto a queue.
      90:  */
      91:
      92: Visible Procedure
      93: stringtoqueue(str, pq)
      94:     register string str;
      95:     register queue *pq;
      96: {
      97:     register value  v;
      98:
      99:     if (str == NULL)
     100:         return;
     101:     v = mk_text(str);
     102:     preptoqueue((node) v, pq);
     103:     release(v);
     104: }
     105:
     106:
     107: /*
     108:  * Append a string to a queue.
     109:  */
     110:
     111: Visible Procedure
     112: addstringtoqueue(pq, str)
     113:     register queue *pq;
     114:     register string str;
     115: {
     116:     register value v = mk_text(str);
     117:
     118:     addtoqueue(pq, (node) v);
     119:     release(v);
     120: }
     121:
     122:
     123: /*
     124:  * Get the first node of a queue and delink it ("pop").
     125:  */
     126:
     127: Visible node
     128: queuebehead(pq)
     129:     register queue *pq;
     130: {
     131:     register node n;
     132:     register queue q = *pq;
     133:
     134:     Assert(q);
     135:
     136:     n = nodecopy(q->q_data);
     137:     *pq = qcopy(q->q_link);
     138:     qrelease(q);
     139:     return n;
     140: }
     141:
     142:
     143: /*
     144:  * Split a node in successive queue elements which are pushed
     145:  * on the queue using preptoqueue.
     146:  * 'Atomic' nodes (texts and holes) are pushed unadorned.
     147:  */
     148:
     149: Visible Procedure
     150: splitnode(n, pq)
     151:     register node n;
     152:     register queue *pq;
     153: {
     154:     register node nn;
     155:     register string *rp;
     156:     register int i;
     157:     register int sym;
     158:
     159:     if (Type(n) == Tex) {
     160:         preptoqueue(n, pq);
     161:         return;
     162:     }
     163:     sym = symbol(n);
     164:     if (sym == Optional)
     165:         return;
     166:     if (sym == Hole) {
     167:         preptoqueue(n, pq);
     168:         return;
     169:     }
     170:
     171:     rp = noderepr(n);
     172:     for (i = nchildren(n); i >= 0; --i) {
     173:         if (rp[i] && rp[i][0])
     174:             stringtoqueue(rp[i], pq);
     175:         if (i) {
     176:             nn = child(n, i);
     177:             if (Type(nn) == Tex || symbol(nn) != Optional)
     178:                 preptoqueue(nn, pq);
     179:         }
     180:     }
     181: }
     182:
     183:
     184: /*
     185:  * Substitute the focus for its parent, appending the remainder of
     186:  * the parent to the queue.
     187:  * The focus must be the first child and not preceded by fixed text.
     188:  * The focus must be allowed in the place of its parent.
     189:  * If any of these conditions is not met, No is returned and nothing
     190:  * is changed.
     191:  */
     192:
     193: Visible bool
     194: resttoqueue(pp, pq)
     195:     register path *pp;
     196:     register queue *pq;
     197: {
     198:     auto queue q = Qnil;
     199:     register path pa = parent(*pp);
     200:     register node n = tree(*pp);
     201:     register int sym = symbol(n);
     202:     /* register markbits x; */
     203:
     204:     if (!pa || ichild(*pp) != 1
     205:         || fwidth(noderepr(tree(pa))[0]) != 0 || !allowed(pa, sym))
     206:         return No;
     207:
     208:     n = nodecopy(n);
     209:     /* x = marks(n); */
     210:     up(pp) || Abort();
     211:     splitnode(tree(*pp), &q);
     212:     noderelease(queuebehead(&q));
     213:     replace(pp, n);
     214:     /* if (x) { */
     215:         /* markpath(pp, x); */ /* Actually, should restore all n's marks? */
     216:     /* } */
     217:     joinqueues(pq, q);
     218:     return Yes;
     219: }
     220:
     221:
     222: /*
     223:  * Like resttoqueue, but exactly from current position in fixed text.
     224:  * Also, it cannot fail.
     225:  */
     226:
     227: Visible Procedure
     228: nosuggtoqueue(ep, pq)
     229:     register environ *ep;
     230:     queue *pq;
     231: {
     232:     auto queue q = Qnil;
     233:     register int i;
     234:     register string *rp;
     235:     register node n;
     236:     register node nn;
     237:     register int sym;
     238:     string str;
     239:
     240:     if (issuggestion(ep))
     241:         return;
     242:     Assert((ep->mode == FHOLE || ep->mode == VHOLE) && (ep->s1&1));
     243:
     244:     n = tree(ep->focus);
     245:     rp = noderepr(n);
     246:     for (i = nchildren(n); i > ep->s1/2; --i) {
     247:         if (!Fw_zero(rp[i]))
     248:             stringtoqueue(rp[i], &q);
     249:         nn = child(n, i);
     250:         sym = symbol(nn);
     251:         if (sym != Optional) {
     252:             preptoqueue(nn, &q);
     253:             if (sym != Hole) {
     254:                 s_downi(ep, i);
     255:                 delfocus(&ep->focus);
     256:                 s_up(ep);
     257:             }
     258:         }
     259:     }
     260:     str = rp[i];
     261:     if (str && str[ep->s2]) /* Push partial first text */
     262:         stringtoqueue(str + ep->s2, &q);
     263:     joinqueues(pq, q);
     264: }
     265:
     266:
     267: /*
     268:  * Check whether the remainder of the current node is all suggestion.
     269:  */
     270:
     271: Visible bool
     272: issuggestion(ep)
     273:     register environ *ep;
     274: {
     275:     register node n;
     276:     register int nch;
     277:     register int sym;
     278:     register int i;
     279:
     280:     if (ep->mode != VHOLE && ep->mode != FHOLE || !(ep->s1&1))
     281:         return No; /* Actually wrong call? */
     282:
     283:     n = tree(ep->focus);
     284:     nch = nchildren(n);
     285:     for (i = ep->s1/2 + 1; i <= nch; ++i) {
     286:         sym = symbol(child(n, i));
     287:         if (sym != Hole && sym != Optional)
     288:             return No;
     289:     }
     290:     return Yes;
     291: }
     292:
     293:
     294: /*
     295:  * See if a node fits in a hole.
     296:  */
     297:
     298: Visible bool
     299: fitnode(pp, n)
     300:     register path *pp;
     301:     register node n;
     302: {
     303:     if (!allowed(*pp, symbol(n)))
     304:         return No;
     305:     replace(pp, nodecopy(n));
     306:     return Yes;
     307: }
     308:
     309:
     310: /*
     311:  * Fit a string in a hole.
     312:  * Returns the number of characters consumed.
     313:  * (This does not have to be the maximum possible, but a reasonable attempt
     314:  * is made.  If the internal buffer is exhausted, it leaves the rest for
     315:  * another call.)
     316:  */
     317:
     318: Visible int
     319: fitstring(pp, str, alt_c)
     320:     register path *pp;
     321:     register string str;
     322:     int alt_c;
     323: {
     324:     environ dummyenv;
     325:     register node n;
     326:     register int ich;
     327:     register int len;
     328:     register string cp;
     329:     char buf[1024];
     330:
     331:     Assert(str);
     332:     if (!str[0])
     333:         return 0;
     334:     if (!insguess(pp, str[0], &dummyenv)) {
     335:         if (!alt_c)
     336:             return 0;
     337:         if (!insguess(pp, alt_c, &dummyenv))
     338:             return 0;
     339:     }
     340:     if (Type(tree(*pp)) == Tex)
     341:         up(pp) || Abort();
     342:     if (dummyenv.mode == FHOLE) {
     343:         cp = noderepr(tree(*pp))[0];
     344:         len = 1;
     345:         if (cp) {
     346:             ++str;
     347:             ++cp;
     348:             while (*str >= ' ' && *str == *cp) {
     349:                 ++len;
     350:                 ++str;
     351:                 ++cp;
     352:             }
     353:         }
     354:         return len;
     355:     }
     356:     if (dummyenv.mode == VHOLE) {
     357:         buf[0] = str[0];
     358:         ++str;
     359:         len = 1;
     360:         n = tree(*pp);
     361:         ich = dummyenv.s1/2;
     362:         while (*str && mayinsert(n, ich, len, *str) && len < sizeof buf - 1) {
     363:             buf[len] = *str;
     364:             ++str;
     365:             ++len;
     366:         }
     367:         if (len > 1) {
     368:             buf[len] = 0;
     369:             downi(pp, ich) || Abort();
     370:             replace(pp, (node) mk_text(buf));
     371:             up(pp) || Abort();
     372:         }
     373:         return len;
     374:     }
     375:     return 1;
     376: }
     377:
     378:
     379: /*
     380:  * Set the focus position (some VHOLE/FHOLE setting, probably)
     381:  * at the 'len'th character from the beginning of the current node.
     382:  * This may involve going to a child or moving beyond the current subtree.
     383:  * Negative 'len' values may be given to indicate negative widths;
     384:  * this is implemented incomplete.
     385:  */
     386:
     387: Visible Procedure
     388: fixfocus(ep, len)
     389:     register environ *ep;
     390:     register int len;
     391: {
     392:     node nn;
     393:     register node n = tree(ep->focus);
     394:     register string *rp;
     395:     register int i = 0;
     396:     register int nch;
     397:     register int w;
     398:
     399:     if (Type(n) == Tex) {
     400:         w = Length((value)n);
     401:         Assert(w >= len && len >= 0);
     402:         if (w > len)
     403:             ep->spflag = No;
     404:         ep->mode = VHOLE;
     405:         ep->s1 = ichild(ep->focus) * 2;
     406:         ep->s2 = len;
     407:         s_up(ep);
     408:         return;
     409:     }
     410:     nch = nchildren(n);
     411:     w = width(n);
     412:     if (len > w && w >= 0) {
     413:         i = ichild(ep->focus); /* Change initial condition for for-loop */
     414:         if (!up(&ep->focus)) {
     415:             ep->mode = ATEND;
     416:             return;
     417:         }
     418:         higher(ep);
     419:         n = tree(ep->focus);
     420:     }
     421:
     422:     rp = noderepr(n);
     423:     for (; i <= nch; ++i) {
     424:         if (i) {
     425:             nn = child(n, i);
     426:             w = width(nn);
     427:             if (w < 0 || w >= len && len >= 0) {
     428:                 s_downi(ep, i);
     429:                 fixfocus(ep, len);
     430:                 return;
     431:             }
     432:             if (len >= 0)
     433:                 len -= w;
     434:         }
     435:         w = Fwidth(rp[i]);
     436:         if (w >= len && len >= 0) {
     437:             if (w > len)
     438:                 ep->spflag = No;
     439:             ep->mode = FHOLE;
     440:             ep->s1 = 2*i + 1;
     441:             ep->s2 = len;
     442:             return;
     443:         }
     444:         else if (w < 0)
     445:             len = 0;
     446:         else
     447:             len -= w;
     448:     }
     449:     ep->mode = ATEND;
     450: }
     451:
     452:
     453: /*
     454:  * Apply, if possible, a special fix relating to spaces:
     455:  * when a space has been interpreted as joining character
     456:  * and we end up in the following hole, but we don't succeed
     457:  * in filling the hole; it is then tried to delete the hole
     458:  * and the space.
     459:  * Usually this doesn't occur, but it may occur when inserting
     460:  * after a space that was already fixed on the screen but now
     461:  * deserves re-interpretation.
     462:  */
     463:
     464: Visible bool
     465: spacefix(ep)
     466:     environ *ep;
     467: {
     468:     path pa;
     469:     node n;
     470:     string *rp;
     471:
     472:     if (ichild(ep->focus) != 2 || symbol(tree(ep->focus)) != Hole)
     473:         return No;
     474:     pa = parent(ep->focus);
     475:     n = tree(pa);
     476:     rp = noderepr(n);
     477:     if (!Fw_zero(rp[0]) || Fwidth(rp[1]) != 1 || rp[1][0] != ' ')
     478:         return No;
     479:     n = firstchild(n);
     480:     if (!allowed(pa, symbol(n)))
     481:         return No;
     482:     s_up(ep);
     483:     replace(&ep->focus, nodecopy(n));
     484:     ep->mode = ATEND;
     485:     ep->spflag = Yes;
     486:     return Yes;
     487: }
     488:
     489:
     490: /*
     491:  * Prepend a subset of a node to a queue.
     492:  */
     493:
     494: Visible Procedure
     495: subsettoqueue(n, s1, s2, pq)
     496:     register node n;
     497:     register int s1;
     498:     register int s2;
     499:     register queue *pq;
     500: {
     501:     register string *rp = noderepr(n);
     502:
     503:     for (; s2 >= s1; --s2) {
     504:         if (s2&1)
     505:             stringtoqueue(rp[s2/2], pq);
     506:         else
     507:             preptoqueue(child(n, s2/2), pq);
     508:     }
     509: }
     510:
     511: #ifdef SHOWBUF
     512:
     513: /*
     514:  * Produce flat text out of a queue's first line, to show it on screen.
     515:  */
     516:
     517: Visible string
     518: querepr(qv)
     519:     value qv;
     520: {
     521:     queue q = (queue)qv;
     522:     node n;
     523:     static char buf[1000]; /***** Cannot overflow? *****/
     524:     string cp;
     525:     string sp;
     526:     string *rp;
     527:     int nch;
     528:     int i;
     529:     int len;
     530:
     531:     cp = buf;
     532:     for (; q; q = q->q_link) {
     533:         n = q->q_data;
     534:         if (Type(n) == Tex) {
     535:             for (sp = Str((value) n); cp < buf+80 && *sp; ++sp) {
     536:                 if (!isprint(*sp) && *sp != ' ')
     537:                     break;
     538:                 *cp++ = *sp;
     539:             }
     540:             if (*sp == '\n') {
     541:                 if (!emptyqueue(q->q_link)) {
     542:                     strcpy(cp, " ...");
     543:                     cp += 4;
     544:                 }
     545:                 break;
     546:             }
     547:         }
     548:         else {
     549:             rp = noderepr(n);
     550:             nch = nchildren(n);
     551:             for (i = 0; i <= nch; ++i) {
     552:                 if (i > 0) {
     553:                     if (Type(child(n, i)) == Tex) {
     554:                         len = Length((value)child(n, i));
     555:                         if (len > 80)
     556:                             len = 80;
     557:                         strncpy(cp, Str((value)child(n, i)), len);
     558:                         cp += len;
     559:                     }
     560:                     else {
     561:                         strcpy(cp, "...");
     562:                         cp += 3;
     563:                     }
     564:                 }
     565:                 if (Fw_negative(rp[i])) {
     566:                     strcpy(cp, " ...");
     567:                     cp += 4;
     568:                     break;
     569:                 }
     570:                 if (Fw_positive(rp[i])) {
     571:                     strcpy(cp, rp[i]);
     572:                     while (*cp)
     573:                         ++cp;
     574:                     if (cp[-1] == '\t' || cp[-1] == '\b')
     575:                         --cp;
     576:                 }
     577:             }
     578:         }
     579:         if (cp >= buf+80) {
     580:             strcpy(buf+76, "...");
     581:             break;
     582:         }
     583:     }
     584:     *cp = 0;
     585:     return buf;
     586: }
     587:
     588: #endif SHOWBUF

#### Defined functions

addstringtoqueue defined in line 111; used 1 times

- in /usr/src/new/PORT/B/src/bed/que2.c line 569

addtoqueue defined in line 76; used 6 times

- in line 118
- in /usr/src/new/PORT/B/src/bed/edit.c line 376
- in /usr/src/new/PORT/B/src/bed/que2.c line 297, 317, 411, 561

fitnode defined in line 298; used 6 times

- in /usr/src/new/PORT/B/src/bed/ins2.c line 153, 162
- in /usr/src/new/PORT/B/src/bed/que2.c line 287, 296, 307, 329

fitstring defined in line 318; used 4 times

- in /usr/src/new/PORT/B/src/bed/ins2.c line 146, 175
- in /usr/src/new/PORT/B/src/bed/que2.c line 420, 715

fixfocus defined in line 387; used 8 times

- in line 429
- in /usr/src/new/PORT/B/src/bed/deco.c line 165
- in /usr/src/new/PORT/B/src/bed/goto.c line 273
- in /usr/src/new/PORT/B/src/bed/ins2.c line 81, 88
- in /usr/src/new/PORT/B/src/bed/que2.c line 124, 453, 467

issuggestion defined in line 271; used 3 times

- in line 240
- in /usr/src/new/PORT/B/src/bed/inse.c line 152, 234

joinqueues defined in line 26; used 3 times

- in line 84, 217, 263

nosuggtoqueue defined in line 227; used 2 times

- in /usr/src/new/PORT/B/src/bed/deco.c line 149
- in /usr/src/new/PORT/B/src/bed/que2.c line 509

preptoqueue defined in line 47; used 12 times

- in line 83, 102, 160, 167, 178, 252, 507
- in /usr/src/new/PORT/B/src/bed/deco.c line 287, 459, 490, 518, 525

querepr defined in line 517; used 2 times

- in /usr/src/new/PORT/B/src/bed/erro.c line 16, 68

queuebehead defined in line 127; used 5 times

- in line 212
- in /usr/src/new/PORT/B/src/bed/deco.c line 515
- in /usr/src/new/PORT/B/src/bed/que2.c line 50
- in /usr/src/new/PORT/B/src/bed/queu.h line 24
- in /usr/src/new/PORT/B/src/bed/save.c line 233

resttoqueue defined in line 193; used 4 times

- in /usr/src/new/PORT/B/src/bed/que2.c line 334, 345, 435, 470

spacefix defined in line 464; used 1 times

- in /usr/src/new/PORT/B/src/bed/que2.c line 437

splitnode defined in line 149; used 3 times

- in line 211
- in /usr/src/new/PORT/B/src/bed/deco.c line 527
- in /usr/src/new/PORT/B/src/bed/que2.c line 78

stringtoqueue defined in line 92; used 8 times

- in line 174, 248, 262, 505
- in /usr/src/new/PORT/B/src/bed/deco.c line 110, 484
- in /usr/src/new/PORT/B/src/bed/que2.c line 93
- in /usr/src/new/PORT/B/src/bed/sugg.c line 360

subsettoqueue defined in line 494; used 4 times

- in /usr/src/new/PORT/B/src/bed/deco.c line 230-231(2), 468, 474

#### 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: 1560 |