Annotation of 43BSD/contrib/B/src/bed/deco.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: deco.c,v 2.3 84/07/19 11:45:12 guido Exp $";
        !             3: 
        !             4: /*
        !             5:  * B editor -- Delete and copy commands.
        !             6:  */
        !             7: 
        !             8: #include <ctype.h>
        !             9: 
        !            10: #include "b.h"
        !            11: #include "erro.h"
        !            12: #include "bobj.h"
        !            13: #include "node.h"
        !            14: #include "gram.h"
        !            15: #include "supr.h"
        !            16: #include "queu.h"
        !            17: 
        !            18: 
        !            19: value copyout(); /* Forward */
        !            20: 
        !            21: /*
        !            22:  * DELETE and COPY currently share a buffer, called the copy buffer.
        !            23:  * (Physically, there is one such a buffer in each environment.)
        !            24:  * In ordinary use, the copy buffer receives the text deleted by the
        !            25:  * last DELETE command (unless it just removed a hole); the COPY command
        !            26:  * can then be used (with the focus on a hole) to copy it back.
        !            27:  * When some portion of text must be held while other text is deleted,
        !            28:  * the COPY command again, but now with the focus on the text to be held,
        !            29:  * copies it to the buffer and deleted text won't overwrite the buffer
        !            30:  * until it is copied back at least once.
        !            31:  * If the buffer holds text that was explicitly copied out but not yet
        !            32:  * copied back in, it is saved on a file when the editor exits, so it can
        !            33:  * be used in the next session; but this is not true for text implicitly
        !            34:  * placed in the buffer through DELETE.
        !            35:  */
        !            36: 
        !            37: /*
        !            38:  * Delete command -- delete the text in the focus, or delete the hole
        !            39:  * if it is only a hole.
        !            40:  */
        !            41: 
        !            42: Visible bool
        !            43: delete(ep)
        !            44:        register environ *ep;
        !            45: {
        !            46:        higher(ep);
        !            47:        shrink(ep);
        !            48:        if (ishole(ep))
        !            49:                return delhole(ep);
        !            50:        if (!ep->copyflag) {
        !            51:                release(ep->copybuffer);
        !            52:                ep->copybuffer = copyout(ep);
        !            53:        }
        !            54:        return delbody(ep);
        !            55: }
        !            56: 
        !            57: 
        !            58: /*
        !            59:  * Delete the focus under the assumption that it contains some text.
        !            60:  */
        !            61: 
        !            62: Visible bool
        !            63: delbody(ep)
        !            64:        register environ *ep;
        !            65: {
        !            66:        ep->changed = Yes;
        !            67: 
        !            68:        subgrow(ep, No); /* Don't ignore spaces */
        !            69:        switch (ep->mode) {
        !            70: 
        !            71:        case SUBRANGE:
        !            72:                if (ep->s1&1)
        !            73:                        return delfixed(ep);
        !            74:                return delvarying(ep);
        !            75: 
        !            76:        case SUBSET:
        !            77:                return delsubset(ep, Yes);
        !            78: 
        !            79:        case SUBLIST:
        !            80:                return delsublist(ep);
        !            81: 
        !            82:        case WHOLE:
        !            83:                return delwhole(ep);
        !            84: 
        !            85:        default:
        !            86:                Abort();
        !            87:                /* NOTREACHED */
        !            88:        }
        !            89: }
        !            90: 
        !            91: 
        !            92: /*
        !            93:  * Delete portion (ep->mode == SUBRANGE) of varying text ((ep->s1&1) == 0).
        !            94:  */
        !            95: 
        !            96: Hidden bool
        !            97: delvarying(ep)
        !            98:        register environ *ep;
        !            99: {
        !           100:        auto queue q = Qnil;
        !           101:        register node n = tree(ep->focus);
        !           102:        auto value v = (value) child(n, ep->s1/2);
        !           103:        register len = Length(v);
        !           104: 
        !           105:        Assert(ep->mode == SUBRANGE && !(ep->s1&1)); /* Wrong call */
        !           106:        Assert(Type(v) == Tex); /* Inconsistent parse tree */
        !           107:        if (ep->s2 == 0
        !           108:                && !mayinsert(tree(ep->focus), ep->s1/2, 0, Str(v)[ep->s3 + 1])) {
        !           109:                /* Cannot do simple substring deletion. */
        !           110:                stringtoqueue(Str(v) + ep->s3 + 1, &q);
        !           111:                delfocus(&ep->focus);
        !           112:                ep->mode = WHOLE;
        !           113:                return app_queue(ep, &q);
        !           114:        }
        !           115:        v = copy(v);
        !           116:        putintrim(&v, ep->s2, len - ep->s3 - 1, "");
        !           117:        s_downi(ep, ep->s1/2);
        !           118:        replace(&ep->focus, (node) v);
        !           119:        s_up(ep);
        !           120:        ep->mode = VHOLE;
        !           121:        return Yes;
        !           122: }
        !           123: 
        !           124: 
        !           125: /*
        !           126:  * Delete portion (ep->mode == SUBRANGE) of fixed text ((ep->s1&1) == 1).
        !           127:  */
        !           128: 
        !           129: Hidden bool
        !           130: delfixed(ep)
        !           131:        register environ *ep;
        !           132: {
        !           133:        register node n = tree(ep->focus);
        !           134:        char buf[15]; /* Long enough for all fixed texts */
        !           135:        register string repr = noderepr(n)[ep->s1/2];
        !           136:        register int len;
        !           137:        queue q = Qnil;
        !           138:        bool ok;
        !           139: 
        !           140:        Assert(ep->mode == SUBRANGE && (ep->s1&1));
        !           141:        if (ep->s1 > 1) {
        !           142:                ep->mode = FHOLE;
        !           143:                return Yes;
        !           144:        }
        !           145:        Assert(fwidth(repr) < sizeof buf - 1);
        !           146:        len = ep->s2;
        !           147:        ep->s2 = ep->s3 + 1;
        !           148:        ep->mode = FHOLE;
        !           149:        nosuggtoqueue(ep, &q);
        !           150:        strcpy(buf, repr);
        !           151:        if (nchildren(tree(ep->focus)) > 0)
        !           152:                buf[len] = 0;
        !           153:        else
        !           154:                strcpy(buf+len, buf+ep->s2);
        !           155:        delfocus(&ep->focus);
        !           156:        ep->mode = WHOLE;
        !           157:        markpath(&ep->focus, 1);
        !           158:        ok = ins_string(ep, buf, &q, 0);
        !           159:        if (!ok) {
        !           160:                qrelease(q);
        !           161:                return No;
        !           162:        }
        !           163:        firstmarked(&ep->focus, 1) || Abort();
        !           164:        unmkpath(&ep->focus, 1);
        !           165:        fixfocus(ep, len);
        !           166:        return app_queue(ep, &q);
        !           167: }
        !           168: 
        !           169: 
        !           170: /*
        !           171:  * Delete focus if ep->mode == SUBSET.
        !           172:  */
        !           173: 
        !           174: Hidden bool
        !           175: delsubset(ep, hack)
        !           176:        register environ *ep;
        !           177:        bool hack;
        !           178: {
        !           179:        auto queue q = Qnil;
        !           180:        auto queue q2 = Qnil;
        !           181:        register node n = tree(ep->focus);
        !           182:        register node nn;
        !           183:        register string *rp = noderepr(n);
        !           184:        register int nch = nchildren(n);
        !           185:        register int i;
        !           186: 
        !           187:        if (hack) {
        !           188:                shrsubset(ep);
        !           189:                if (ep->s1 == ep->s2 && !(ep->s1&1)) {
        !           190:                        nn = child(tree(ep->focus), ep->s1/2);
        !           191:                        if (fwidth(noderepr(nn)[0]) < 0) {
        !           192:                                /* It starts with a newline, leave the newline */
        !           193:                                s_downi(ep, ep->s1/2);
        !           194:                                ep->mode = SUBSET;
        !           195:                                ep->s1 = 2;
        !           196:                                ep->s2 = 2*nchildren(nn) + 1;
        !           197:                                return delsubset(ep, hack);
        !           198:                        }
        !           199:                }
        !           200:                subgrsubset(ep, No); /* Undo shrsubset */
        !           201:                if (ep->s2 == 3 && rp[1] && Strequ(rp[1], "\t"))
        !           202:                        --ep->s2; /* Hack for deletion of unit-head or if/for/wh. head */
        !           203:        }
        !           204:        if (ep->s1 == 1 && Fw_negative(rp[0]))
        !           205:                ++ep->s1; /* Hack for deletion of test-suite or refinement head */
        !           206: 
        !           207:        if (Fw_zero(rp[0]) ? (ep->s2 < 3 || ep->s1 > 3) : ep->s1 > 1) {
        !           208:                /* No deep structural change */
        !           209:                for (i = (ep->s1+1)/2; i <= ep->s2/2; ++i) {
        !           210:                        s_downi(ep, i);
        !           211:                        delfocus(&ep->focus);
        !           212:                        s_up(ep);
        !           213:                }
        !           214:                if (ep->s1&1) {
        !           215:                        ep->mode = FHOLE;
        !           216:                        ep->s2 = 0;
        !           217:                }
        !           218:                else if (Type(child(tree(ep->focus), ep->s1/2)) == Tex) {
        !           219:                        ep->mode = VHOLE;
        !           220:                        ep->s2 = 0;
        !           221:                }
        !           222:                else {
        !           223:                        s_downi(ep, ep->s1/2);
        !           224:                        ep->mode = ATBEGIN;
        !           225:                }
        !           226:                return Yes;
        !           227:        }
        !           228: 
        !           229:        balance(ep); /* Make balanced \t - \b pairs */
        !           230:        subsettoqueue(n, 1, ep->s1-1, &q);
        !           231:        subsettoqueue(n, ep->s2+1, 2*nch+1, &q2);
        !           232:        nonewline(&q2); /* Wonder what will happen...? */
        !           233:        delfocus(&ep->focus);
        !           234:        ep->mode = ATBEGIN;
        !           235:        leftvhole(ep);
        !           236:        if (!ins_queue(ep, &q, &q2)) {
        !           237:                qrelease(q2);
        !           238:                return No;
        !           239:        }
        !           240:        return app_queue(ep, &q2);
        !           241: }
        !           242: 
        !           243: 
        !           244: /*
        !           245:  * Delete the focus if ep->mode == SUBLIST.
        !           246:  */
        !           247: 
        !           248: delsublist(ep)
        !           249:        register environ *ep;
        !           250: {
        !           251:        register node n;
        !           252:        register int i;
        !           253:        register int sym;
        !           254:        queue q = Qnil;
        !           255:        bool flag;
        !           256: 
        !           257:        Assert(ep->mode == SUBLIST);
        !           258:        n = tree(ep->focus);
        !           259:        flag = fwidth(noderepr(n)[0]) < 0;
        !           260:        for (i = ep->s3; i > 0; --i) {
        !           261:                n = lastchild(n);
        !           262:                Assert(n);
        !           263:        }
        !           264:        if (flag) {
        !           265:                n = nodecopy(n);
        !           266:                s_down(ep);
        !           267:                do {
        !           268:                        delfocus(&ep->focus);
        !           269:                } while (rite(&ep->focus));
        !           270:                if (!allowed(ep->focus, symbol(n))) {
        !           271:                        error(DEL_REM); /* The remains wouldn't fit */
        !           272:                        noderelease(n);
        !           273:                        return No;
        !           274:                }
        !           275:                replace(&ep->focus, n);
        !           276:                s_up(ep);
        !           277:                s_down(ep); /* I.e., to leftmost sibling */
        !           278:                ep->mode = WHOLE;
        !           279:                return Yes;
        !           280:        }
        !           281:        sym = symbol(n);
        !           282:        if (sym == Optional || sym == Hole) {
        !           283:                delfocus(&ep->focus);
        !           284:                ep->mode = WHOLE;
        !           285:        }
        !           286:        else if (!allowed(ep->focus, sym)) {
        !           287:                preptoqueue(n, &q);
        !           288:                delfocus(&ep->focus);
        !           289:                ep->mode = WHOLE;
        !           290:                return app_queue(ep, &q);
        !           291:        }
        !           292:        else {
        !           293:                replace(&ep->focus, nodecopy(n));
        !           294:                ep->mode = ATBEGIN;
        !           295:        }
        !           296:        return Yes;
        !           297: }
        !           298: 
        !           299: 
        !           300: /*
        !           301:  * Delete the focus if ep->mode == WHOLE.
        !           302:  */
        !           303: 
        !           304: Hidden bool
        !           305: delwhole(ep)
        !           306:        register environ *ep;
        !           307: {
        !           308:        register int sym = symbol(tree(ep->focus));
        !           309: 
        !           310:        Assert(ep->mode == WHOLE);
        !           311:        if (sym == Optional || sym == Hole)
        !           312:                return No;
        !           313:        delfocus(&ep->focus);
        !           314:        return Yes;
        !           315: }
        !           316: 
        !           317: 
        !           318: /*
        !           319:  * Delete the focus if it is only a hole.
        !           320:  * Assume shrink() has been called before!
        !           321:  */
        !           322: 
        !           323: Hidden bool
        !           324: delhole(ep)
        !           325:        register environ *ep;
        !           326: {
        !           327:        node n;
        !           328:        int sym;
        !           329:        bool flag = No;
        !           330: 
        !           331:        switch (ep->mode) {
        !           332:        
        !           333:        case ATBEGIN:
        !           334:        case VHOLE:
        !           335:        case FHOLE:
        !           336:        case ATEND:
        !           337:                return widen(ep);
        !           338: 
        !           339:        case WHOLE:
        !           340:                Assert((sym = symbol(tree(ep->focus))) == Optional || sym == Hole);
        !           341:                if (ichild(ep->focus) != 1)
        !           342:                        break;
        !           343:                if (!up(&ep->focus))
        !           344:                        return No;
        !           345:                higher(ep);
        !           346:                ep->mode = SUBSET;
        !           347:                ep->s1 = 2;
        !           348:                ep->s2 = 2;
        !           349:                if (fwidth(noderepr(tree(ep->focus))[0]) < 0) {
        !           350:                        flag = Yes;
        !           351:                        ep->s2 = 3; /* Extend to rest of line */
        !           352:                }
        !           353:        }
        !           354: 
        !           355:        ep->changed = Yes;
        !           356:        grow(ep);
        !           357: 
        !           358:        switch (ep->mode) {
        !           359: 
        !           360:        case SUBSET:
        !           361:                if (!delsubset(ep, No))
        !           362:                        return No;
        !           363:                if (!flag)
        !           364:                        return widen(ep);
        !           365:                leftvhole(ep);
        !           366:                oneline(ep);
        !           367:                return Yes;
        !           368: 
        !           369:        case SUBLIST:
        !           370:                n = tree(ep->focus);
        !           371:                n = lastchild(n);
        !           372:                sym = symbol(n);
        !           373:                if (!allowed(ep->focus, sym)) {
        !           374:                        error(DEL_REM); /* The remains wouldn't fit */
        !           375:                        return No;
        !           376:                }
        !           377:                flag = samelevel(sym, symbol(tree(ep->focus)));
        !           378:                replace(&ep->focus, nodecopy(n));
        !           379:                if (flag) {
        !           380:                        ep->mode = SUBLIST;
        !           381:                        ep->s3 = 1;
        !           382:                }
        !           383:                else
        !           384:                        ep->mode = WHOLE;
        !           385:                return Yes;
        !           386: 
        !           387:        case WHOLE:
        !           388:                Assert(!parent(ep->focus)); /* Must be at root! */
        !           389:                return No;
        !           390: 
        !           391:        default:
        !           392:                Abort();
        !           393:                /* NOTREACHED */
        !           394: 
        !           395:        }
        !           396: }
        !           397: 
        !           398: 
        !           399: /*
        !           400:  * Subroutine to delete the focus.
        !           401:  */
        !           402: 
        !           403: Visible Procedure
        !           404: delfocus(pp)
        !           405:        register path *pp;
        !           406: {
        !           407:        register path pa = parent(*pp);
        !           408:        register int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
        !           409: 
        !           410:        replace(pp, child(gram(sympa), ichild(*pp)));
        !           411: }
        !           412: 
        !           413: 
        !           414: /*
        !           415:  * Copy command -- copy the focus to the copy buffer if it contains
        !           416:  * some text, copy the copy buffer into the focus if the focus is
        !           417:  * empty (just a hole).
        !           418:  */
        !           419: 
        !           420: Visible bool
        !           421: copyinout(ep)
        !           422:        register environ *ep;
        !           423: {
        !           424:        shrink(ep);
        !           425:        if (!ishole(ep)) {
        !           426:                release(ep->copybuffer);
        !           427:                ep->copybuffer = copyout(ep);
        !           428:                ep->copyflag = !!ep->copybuffer;
        !           429:                return ep->copyflag;
        !           430:        }
        !           431:        else {
        !           432:                fixit(ep); /* Make sure it looks like a hole now */
        !           433:                if (!copyin(ep, (queue) ep->copybuffer))
        !           434:                        return No;
        !           435:                ep->copyflag = No;
        !           436:                return Yes;
        !           437:        }
        !           438: }
        !           439: 
        !           440: 
        !           441: /*
        !           442:  * Copy the focus to the copy buffer.
        !           443:  */
        !           444: 
        !           445: Visible value
        !           446: copyout(ep)
        !           447:        register environ *ep;
        !           448: {
        !           449:        auto queue q = Qnil;
        !           450:        auto path p;
        !           451:        register node n;
        !           452:        register value v;
        !           453:        char buf[15];
        !           454:        register string *rp;
        !           455:        register int i;
        !           456: 
        !           457:        switch (ep->mode) {
        !           458:        case WHOLE:
        !           459:                preptoqueue(tree(ep->focus), &q);
        !           460:                break;
        !           461:        case SUBLIST:
        !           462:                p = pathcopy(ep->focus);
        !           463:                for (i = ep->s3; i > 0; --i)
        !           464:                        downrite(&p) || Abort();
        !           465:                for (i = ep->s3; i > 0; --i) {
        !           466:                        up(&p) || Abort();
        !           467:                        n = tree(p);
        !           468:                        subsettoqueue(n, 1, 2*nchildren(n) - 1, &q);
        !           469:                }
        !           470:                pathrelease(p);
        !           471:                break;
        !           472:        case SUBSET:
        !           473:                balance(ep);
        !           474:                subsettoqueue(tree(ep->focus), ep->s1, ep->s2, &q);
        !           475:                break;
        !           476:        case SUBRANGE:
        !           477:                Assert(ep->s3 >= ep->s2);
        !           478:                if (ep->s1&1) { /* Fixed text */
        !           479:                        Assert(ep->s3 - ep->s2 + 1 < sizeof buf);
        !           480:                        rp = noderepr(tree(ep->focus));
        !           481:                        Assert(ep->s2 < Fwidth(rp[ep->s1/2]));
        !           482:                        strncpy(buf, rp[ep->s1/2] + ep->s2, ep->s3 - ep->s2 + 1);
        !           483:                        buf[ep->s3 - ep->s2 + 1] = 0;
        !           484:                        stringtoqueue(buf, &q);
        !           485:                }
        !           486:                else { /* Varying text */
        !           487:                        v = (value) child(tree(ep->focus), ep->s1/2);
        !           488:                        Assert(Type(v) == Tex);
        !           489:                        v = trim(v, ep->s2, Length(v) - ep->s3 - 1);
        !           490:                        preptoqueue((node)v, &q);
        !           491:                        release(v);
        !           492:                }
        !           493:                break;
        !           494:        default:
        !           495:                Abort();
        !           496:        }
        !           497:        nonewline(&q);
        !           498:        return (value)q;
        !           499: }
        !           500: 
        !           501: 
        !           502: /*
        !           503:  * Subroutine to ensure the copy buffer doesn't start with a newline.
        !           504:  */
        !           505: 
        !           506: Hidden Procedure
        !           507: nonewline(pq)
        !           508:        register queue *pq;
        !           509: {
        !           510:        register node n;
        !           511:        register int c;
        !           512: 
        !           513:        if (!emptyqueue(*pq)) {
        !           514:                for (;;) {
        !           515:                        n = queuebehead(pq);
        !           516:                        if (Type(n) == Tex) {
        !           517:                                if (Str((value) n)[0] != '\n')
        !           518:                                        preptoqueue(n, pq);
        !           519:                                noderelease(n);
        !           520:                                break;
        !           521:                        }
        !           522:                        else {
        !           523:                                c = nodechar(n);
        !           524:                                if (c != '\n')
        !           525:                                        preptoqueue(n, pq);
        !           526:                                else
        !           527:                                        splitnode(n, pq);
        !           528:                                noderelease(n);
        !           529:                                if (c != '\n')
        !           530:                                        break;
        !           531:                        }
        !           532:                }
        !           533:        }
        !           534: }
        !           535: 
        !           536: 
        !           537: /*
        !           538:  * Refinement for copyout, case SUBSET: make sure that \t is balanced with \b.
        !           539:  * Actually it can only handle the case where a \t is in the subset and the
        !           540:  * matching \b is immediately following.
        !           541:  */
        !           542: 
        !           543: Hidden Procedure
        !           544: balance(ep)
        !           545:        environ *ep;
        !           546: {
        !           547:        string *rp = noderepr(tree(ep->focus));
        !           548:        int i;
        !           549:        int level = 0;
        !           550: 
        !           551:        Assert(ep->mode == SUBSET);
        !           552:        for (i = ep->s1/2; i*2 < ep->s2; ++i) {
        !           553:                if (rp[i]) {
        !           554:                        if (index(rp[i], '\t'))
        !           555:                                ++level;
        !           556:                        else if (index(rp[i], '\b'))
        !           557:                                --level;
        !           558:                }
        !           559:        }
        !           560:        if (level > 0 && i*2 == ep->s2 && rp[i] && index(rp[i], '\b'))
        !           561:                ep->s2 = 2*i + 1;
        !           562: }
        !           563: 
        !           564: 
        !           565: /*
        !           566:  * Copy the copy buffer to the focus.
        !           567:  */
        !           568: 
        !           569: Hidden bool
        !           570: copyin(ep, q)
        !           571:        register environ *ep;
        !           572:        /*auto*/ queue q;
        !           573: {
        !           574:        auto queue q2 = Qnil;
        !           575: 
        !           576:        if (!q) {
        !           577:                error(COPY_EMPTY); /* Empty copy buffer */
        !           578:                return No;
        !           579:        }
        !           580:        ep->changed = Yes;
        !           581:        q = qcopy(q);
        !           582:        if (!ins_queue(ep, &q, &q2)) {
        !           583:                qrelease(q2);
        !           584:                return No;
        !           585:        }
        !           586:        return app_queue(ep, &q2);
        !           587: }
        !           588: 
        !           589: 
        !           590: /*
        !           591:  * Find out whether the focus looks like a hole or if it has some real
        !           592:  * text in it.
        !           593:  * Assumes shrink(ep) has already been performed.
        !           594:  */
        !           595: 
        !           596: Visible bool
        !           597: ishole(ep)
        !           598:        register environ *ep;
        !           599: {
        !           600:        register int sym;
        !           601: 
        !           602:        switch (ep->mode) {
        !           603:        
        !           604:        case ATBEGIN:
        !           605:        case ATEND:
        !           606:        case VHOLE:
        !           607:        case FHOLE:
        !           608:                return Yes;
        !           609: 
        !           610:        case SUBLIST:
        !           611:        case SUBRANGE:
        !           612:                return No;
        !           613: 
        !           614:        case SUBSET:
        !           615:                return colonhack(ep); /* (Side-effect!) */
        !           616: 
        !           617:        case WHOLE:
        !           618:                sym = symbol(tree(ep->focus));
        !           619:                return sym == Optional || sym == Hole;
        !           620: 
        !           621:        default:
        !           622:                Abort();
        !           623:                /* NOTREACHED */
        !           624:        }
        !           625: }
        !           626: 
        !           627: 
        !           628: /*
        !           629:  * Amendment to ishole so that it categorizes '?: ?' as a hole.
        !           630:  * This makes deletion of empty refinements / alternative-suites
        !           631:  * easier (Steven).
        !           632:  */
        !           633: 
        !           634: Hidden bool
        !           635: colonhack(ep)
        !           636:        environ *ep;
        !           637: {
        !           638:        node n = tree(ep->focus);
        !           639:        node n1;
        !           640:        string *rp = noderepr(n);
        !           641:        int i;
        !           642:        int sym;
        !           643: 
        !           644:        for (i = ep->s1; i <= ep->s2; ++i) {
        !           645:                if (i&1) {
        !           646:                        if (!allright(rp[i/2]))
        !           647:                                return No;
        !           648:                }
        !           649:                else {
        !           650:                        n1 = child(n, i/2);
        !           651:                        if (Type(n1) == Tex)
        !           652:                                return No;
        !           653:                        sym = symbol(n1);
        !           654:                        if (sym != Hole && sym != Optional)
        !           655:                                return No;
        !           656:                }
        !           657:        }
        !           658:        return Yes;
        !           659: }
        !           660: 
        !           661: 
        !           662: /*
        !           663:  * Refinement for colonhack.  Recognize strings that are almost blank
        !           664:  * (i.e. containing only spaces, colons and the allowed control characters).
        !           665:  */
        !           666: 
        !           667: Hidden bool
        !           668: allright(repr)
        !           669:        string repr;
        !           670: {
        !           671:        if (repr) {
        !           672:                for (; *repr; ++repr) {
        !           673:                        if (!index(": \t\b\n\r", *repr))
        !           674:                                return No;
        !           675:                }
        !           676:        }
        !           677:        return Yes;
        !           678: }

unix.superglobalmegacorp.com

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