Annotation of 43BSDTahoe/new/B/src/bed/que1.c, revision 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.