Annotation of 43BSD/contrib/B/src/bed/que1.c, revision 1.1.1.1

1.1       root        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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.