Annotation of 43BSDTahoe/new/B/src/bed/supr.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: supr.c,v 2.3 84/07/23 13:03:15 guido Exp $";
        !             3: 
        !             4: /*
        !             5:  * B editor -- Superroutines.
        !             6:  */
        !             7: 
        !             8: #include "b.h"
        !             9: #include "feat.h"
        !            10: #include "bobj.h"
        !            11: #include "node.h"
        !            12: #include "supr.h"
        !            13: #include "gram.h"
        !            14: 
        !            15: /*
        !            16:  * Compute the length of the ep->s1'th item of node tree(ep->focus).
        !            17:  */
        !            18: 
        !            19: Visible int
        !            20: lenitem(ep)
        !            21:        register environ *ep;
        !            22: {
        !            23:        register node n = tree(ep->focus);
        !            24:        register node nn;
        !            25: 
        !            26:        if (ep->s1&1) /* Fixed text */
        !            27:                return fwidth(noderepr(n)[ep->s1/2]);
        !            28:        /* Else, variable text or a whole node */
        !            29:        nn = child(n, ep->s1/2);
        !            30:        return width(nn);
        !            31: }
        !            32: 
        !            33: 
        !            34: /*
        !            35:  * Find the largest possible representation of the focus.
        !            36:  * E.g., a WHOLE can also be represented as a SUBSET of its parent,
        !            37:  * provided it has a parent.
        !            38:  * Also, a SUBSET may be extended with some empty left and right
        !            39:  * items and then look like a WHOLE, etc.
        !            40:  * This process is repeated until no more improvements can be made.
        !            41:  */
        !            42: 
        !            43: Visible Procedure
        !            44: grow(ep)
        !            45:        environ *ep;
        !            46: {
        !            47:        subgrow(ep, Yes);
        !            48: }
        !            49: 
        !            50: Visible Procedure
        !            51: subgrow(ep, ignorespaces)
        !            52:        register environ *ep;
        !            53:        bool ignorespaces;
        !            54: {
        !            55:        register node n;
        !            56:        register int sym;
        !            57:        register int i;
        !            58:        register int len;
        !            59:        register string repr;
        !            60: 
        !            61:        switch (ep->mode) {
        !            62:        case ATBEGIN:
        !            63:        case ATEND:
        !            64:        case VHOLE:
        !            65:        case FHOLE:
        !            66:                ritevhole(ep);
        !            67:                if (ep->mode != FHOLE && ep->mode != VHOLE || lenitem(ep) == 0)
        !            68:                        leftvhole(ep);
        !            69: 
        !            70:        }
        !            71: 
        !            72:        for (;;) {
        !            73:                n = tree(ep->focus);
        !            74:                sym = symbol(n);
        !            75: 
        !            76:                switch (ep->mode) {
        !            77: 
        !            78:                case VHOLE:
        !            79:                case FHOLE:
        !            80:                        if ((sym == Optional || sym == Hole) && ep->s2 == 0) {
        !            81:                                ep->mode = WHOLE;
        !            82:                                continue;
        !            83:                        }
        !            84:                        if (lenitem(ep) <= 0) {
        !            85:                                ep->mode = SUBSET;
        !            86:                                ep->s2 = ep->s1;
        !            87:                                continue;
        !            88:                        }
        !            89:                        return;
        !            90: 
        !            91:                case ATBEGIN:
        !            92:                case ATEND:
        !            93:                        if (sym == Optional || sym == Hole) {
        !            94:                                ep->mode = WHOLE;
        !            95:                                continue;
        !            96:                        }
        !            97:                        return;
        !            98: 
        !            99:                case SUBRANGE:
        !           100:                        if (ep->s1&1) {
        !           101:                                repr = noderepr(n)[ep->s1/2];
        !           102:                                len = fwidth(repr);
        !           103:                                if (!ignorespaces) {
        !           104:                                  while (ep->s2 > 0 && repr[ep->s2-1] == ' ')
        !           105:                                        --ep->s2;
        !           106:                                  while (ep->s3 < len && repr[ep->s3+1] == ' ')
        !           107:                                        ++ep->s3;
        !           108:                                }
        !           109:                        }
        !           110:                        else
        !           111:                                len = Length((value) firstchild(n));
        !           112:                        if (ep->s2 == 0 && ep->s3 >= len - 1) {
        !           113:                                ep->mode = SUBSET;
        !           114:                                ep->s2 = ep->s1;
        !           115:                                continue;
        !           116:                        }
        !           117:                        return;
        !           118: 
        !           119:                case SUBSET:
        !           120:                        subgrsubset(ep, ignorespaces);
        !           121:                        if (ep->s1 == 1) {
        !           122:                                if (ep->s2 == 2*nchildren(n) + 1) {
        !           123:                                        ep->mode = WHOLE;
        !           124:                                        continue;
        !           125:                                }
        !           126:                                if (ep->s2 == 2*nchildren(n) - 1 && issublist(sym)) {
        !           127:                                        ep->mode = SUBLIST;
        !           128:                                        ep->s3 = 1;
        !           129:                                        return;
        !           130:                                }
        !           131:                        }
        !           132:                        return;
        !           133: 
        !           134:                case SUBLIST:
        !           135:                        for (i = ep->s3; i > 0; --i)
        !           136:                                n = lastchild(n);
        !           137:                        sym = symbol(n);
        !           138:                        if (sym == Optional) {
        !           139:                                ep->mode = WHOLE;
        !           140:                                continue;
        !           141:                        }
        !           142:                        return;
        !           143: 
        !           144:                case WHOLE:
        !           145:                        ep->s1 = 2*ichild(ep->focus);
        !           146:                        if (up(&ep->focus)) {
        !           147:                                ep->mode = SUBSET;
        !           148:                                ep->s2 = ep->s1;
        !           149:                                higher(ep);
        !           150:                                continue;
        !           151:                        }
        !           152:                        return; /* Leave as WHOLE if there is no parent */
        !           153: 
        !           154:                default:
        !           155:                        Abort();
        !           156:                        /* NOTREACHED */
        !           157: 
        !           158:                }
        !           159:                
        !           160:        }
        !           161:        /* Not reached */
        !           162: }
        !           163: 
        !           164: 
        !           165: /*
        !           166:  * Ditto to find smallest possible representation.
        !           167:  */
        !           168: 
        !           169: Visible Procedure
        !           170: shrink(ep)
        !           171:        register environ *ep;
        !           172: {
        !           173:        register node n;
        !           174:        register int sym;
        !           175: 
        !           176:        for (;;) {
        !           177:                n = tree(ep->focus);
        !           178:                sym = symbol(n);
        !           179: 
        !           180:                switch (ep->mode) {
        !           181: 
        !           182:                case WHOLE:
        !           183:                        if (sym == Hole || sym == Optional)
        !           184:                                return;
        !           185:                        ep->mode = SUBSET;
        !           186:                        ep->s1 = 1;
        !           187:                        ep->s2 = 2*nchildren(n) + 1;
        !           188:                        continue;
        !           189: 
        !           190:                case SUBLIST:
        !           191:                        if (sym == Hole || sym == Optional) {
        !           192:                                ep->mode = WHOLE;
        !           193:                                return;
        !           194:                        }
        !           195:                        if (ep->s3 == 1) {
        !           196:                                ep->mode = SUBSET;
        !           197:                                ep->s1 = 1;
        !           198:                                ep->s2 = 2*nchildren(n) - 1;
        !           199:                                continue;
        !           200:                        }
        !           201:                        return;
        !           202: 
        !           203:                case SUBSET:
        !           204:                        if (sym == Hole || sym == Optional) {
        !           205:                                ep->mode = WHOLE;
        !           206:                                return;
        !           207:                        }
        !           208:                        shrsubset(ep);
        !           209:                        if (ep->s1 == ep->s2) {
        !           210:                                if (isunititem(ep)) {
        !           211:                                        ep->mode = SUBRANGE;
        !           212:                                        ep->s2 = 0;
        !           213:                                        ep->s3 = lenitem(ep) - 1;
        !           214:                                        return;
        !           215:                                }
        !           216:                                else {
        !           217:                                        s_downi(ep, ep->s1/2);
        !           218:                                        ep->mode = WHOLE;
        !           219:                                        continue;
        !           220:                                }
        !           221:                        }
        !           222:                        return;
        !           223: 
        !           224:                case SUBRANGE:
        !           225:                        if (sym == Optional || sym == Hole)
        !           226:                                ep->mode = WHOLE;
        !           227:                        return;
        !           228: 
        !           229:                case ATBEGIN:
        !           230:                        ritevhole(ep);
        !           231:                        if (ep->mode == ATBEGIN) {
        !           232:                                if (sym == Optional || sym == Hole)
        !           233:                                        ep->mode = WHOLE;
        !           234:                                return;
        !           235:                        }
        !           236:                        continue;
        !           237: 
        !           238:                case FHOLE:
        !           239:                case VHOLE:
        !           240:                        ritevhole(ep);
        !           241:                        if (ep->mode != VHOLE && ep->mode != FHOLE)
        !           242:                                continue;
        !           243:                        sym = symbol(tree(ep->focus));
        !           244:                        if (sym == Optional || sym == Hole && ep->s2 == 0)
        !           245:                                ep->mode = WHOLE;
        !           246:                        return;
        !           247: 
        !           248:                case ATEND:
        !           249:                        return;
        !           250: 
        !           251:                default:
        !           252:                        Abort();
        !           253:                        /* NOTREACHED */
        !           254: 
        !           255:                }
        !           256:        }
        !           257:        /* Not reached */
        !           258: 
        !           259: }
        !           260: 
        !           261: 
        !           262: /*
        !           263:  * Subroutine to find the largest way to describe a SUBSET focus
        !           264:  * (modulo surrounding blanks and newlines).
        !           265:  */
        !           266: 
        !           267: Visible Procedure
        !           268: growsubset(ep)
        !           269:        environ *ep;
        !           270: {
        !           271:        subgrsubset(ep, Yes);
        !           272: }
        !           273: 
        !           274: Visible Procedure
        !           275: subgrsubset(ep, ignorespaces)
        !           276:        register environ *ep;
        !           277:        bool ignorespaces;
        !           278: {
        !           279:        register node n = tree(ep->focus);
        !           280:        register string *rp = noderepr(n);
        !           281:        register nch21 = nchildren(n)*2 + 1;
        !           282:        register int i;
        !           283: 
        !           284:        Assert(ep->mode == SUBSET);
        !           285:        for (i = ep->s1; i > 1 && subisnull(n, rp, i-1, ignorespaces); --i)
        !           286:                ;
        !           287:        ep->s1 = i;
        !           288:        for (i = ep->s2; i < nch21 && subisnull(n, rp, i+1, ignorespaces); ++i)
        !           289:                ;
        !           290:        ep->s2 = i;
        !           291: }
        !           292: 
        !           293: 
        !           294: /*
        !           295:  * Ditto for the smallest way.
        !           296:  */
        !           297: 
        !           298: Visible Procedure /* Ought to be Hidden */
        !           299: shrsubset(ep)
        !           300:        register environ *ep;
        !           301: {
        !           302:        register node n = tree(ep->focus);
        !           303:        register string *rp = noderepr(n);
        !           304:        register int s1 = ep->s1;
        !           305:        register int s2 = ep->s2;
        !           306: 
        !           307:        for (; s1 < s2 && isnull(n, rp, s1); ++s1)
        !           308:                ;
        !           309:        ep->s1 = s1;
        !           310:        for (; s2 > s1 && isnull(n, rp, s2); --s2)
        !           311:                ;
        !           312:        ep->s2 = s2;
        !           313: }
        !           314: 
        !           315: 
        !           316: /*
        !           317:  * Subroutine for grow/shrink to see whether item i is (almost) invisible.
        !           318:  */
        !           319: 
        !           320: Visible bool
        !           321: isnull(n, rp, i)
        !           322:        node n;
        !           323:        string *rp;
        !           324:        int i;
        !           325: {
        !           326:        return subisnull(n, rp, i, Yes);
        !           327: }
        !           328: 
        !           329: Hidden Procedure
        !           330: subisnull(n, rp, i, ignorespaces)
        !           331:        register node n;
        !           332:        register string *rp;
        !           333:        register int i;
        !           334:        bool ignorespaces;
        !           335: {
        !           336:        register string repr;
        !           337:        register node nn;
        !           338: 
        !           339:        if (i&1) { /* Fixed text */
        !           340:                repr = rp[i/2];
        !           341:                return !Fw_positive(repr) || ignorespaces && allspaces(repr);
        !           342:        }
        !           343:        nn = child(n, i/2);
        !           344:        return width(nn) == 0;
        !           345: }
        !           346: 
        !           347: 
        !           348: /*
        !           349:  * Find the rightmost VHOLE which would look the same as the current one.
        !           350:  */
        !           351: 
        !           352: Visible Procedure
        !           353: ritevhole(ep)
        !           354:        register environ *ep;
        !           355: {
        !           356:        register node n;
        !           357:        register int ich;
        !           358:        register int len;
        !           359:        register int s1save;
        !           360: 
        !           361:        for (;;) {
        !           362:                n = tree(ep->focus);
        !           363: 
        !           364:                switch (ep->mode) {
        !           365: 
        !           366:                case WHOLE:
        !           367:                        ep->mode = ATEND;
        !           368:                        break;
        !           369: 
        !           370:                case VHOLE:
        !           371:                case FHOLE:
        !           372:                        len = lenitem(ep);
        !           373:                        Assert(len >= 0);
        !           374:                        if (ep->s2 < len)
        !           375:                                return; /* Hole in middle of string */
        !           376:                        s1save = ep->s1;
        !           377:                        if (nextitem(ep)) {
        !           378:                                if (isunititem(ep)) {
        !           379:                                        ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
        !           380:                                        ep->s2 = 0;
        !           381:                                }
        !           382:                                else if (fwidth(noderepr(child(n, ep->s1/2))[0]) < 0) {
        !           383:                                        /* Next item begins with newline -- avoid */
        !           384:                                        ep->s1 = s1save;
        !           385:                                        return;
        !           386:                                }
        !           387:                                else {
        !           388:                                        s_downi(ep, ep->s1/2);
        !           389:                                        ep->mode = ATBEGIN;
        !           390:                                }
        !           391:                                break;
        !           392:                        }
        !           393:                        ep->mode = ATEND;
        !           394:                        /* Fall through */
        !           395:                case ATEND:
        !           396:                        if (!parent(ep->focus) || width(n) < 0)
        !           397:                                return;
        !           398:                        ich = ichild(ep->focus);
        !           399:                        ep->s1 = 2*ich;
        !           400:                        s_up(ep);
        !           401:                        if (nextitem(ep)) {
        !           402:                                /* Note -- negative width cannot occur (see test above) */
        !           403:                                if (isunititem(ep)) {
        !           404:                                        ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
        !           405:                                        ep->s2 = 0;
        !           406:                                }
        !           407:                                else {
        !           408:                                        ep->mode = ATBEGIN;
        !           409:                                        s_downi(ep, ep->s1/2);
        !           410:                                }
        !           411:                                break;
        !           412:                        }
        !           413:                        continue;
        !           414: 
        !           415:                case ATBEGIN:
        !           416:                        if (fwidth(noderepr(n)[0]) < 0)
        !           417:                                return; /* Already at dangerous position */
        !           418:                        ep->mode = FHOLE;
        !           419:                        ep->s1 = 1;
        !           420:                        ep->s2 = 0;
        !           421:                        continue;
        !           422: 
        !           423:                default:
        !           424:                        Abort();
        !           425:                        /* NOTREACHED */
        !           426: 
        !           427:                }
        !           428:        }
        !           429: }
        !           430: 
        !           431: 
        !           432: /*
        !           433:  * Ditto to the left.
        !           434:  */
        !           435: 
        !           436: Visible Procedure
        !           437: leftvhole(ep)
        !           438:        register environ *ep;
        !           439: {
        !           440:        register int ich;
        !           441: 
        !           442:        for (;;) {
        !           443:                switch (ep->mode) {
        !           444: 
        !           445:                case WHOLE:
        !           446:                        ep->mode = ATBEGIN;
        !           447:                        break;
        !           448: 
        !           449:                case VHOLE:
        !           450:                case FHOLE:
        !           451:                        if (ep->s2 > 0)
        !           452:                                return;
        !           453:                        if (previtem(ep)) {
        !           454:                                if (isunititem(ep)) {
        !           455:                                        ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
        !           456:                                        ep->s2 = lenitem(ep);
        !           457:                                }
        !           458:                                else {
        !           459:                                        s_downi(ep, ep->s1/2);
        !           460:                                        ep->mode = ATEND;
        !           461:                                }
        !           462:                        }
        !           463:                        else if (fwidth(noderepr(tree(ep->focus))[0]) < 0)
        !           464:                                return;
        !           465:                        else
        !           466:                                ep->mode = ATBEGIN;
        !           467:                        continue;
        !           468: 
        !           469:                case ATBEGIN:
        !           470:                        ich = ichild(ep->focus);
        !           471:                        if (!up(&ep->focus))
        !           472:                                return;
        !           473:                        higher(ep);
        !           474:                        ep->s1 = 2*ich;
        !           475:                        if (prevnnitem(ep)) {
        !           476:                                if (isunititem(ep)) {
        !           477:                                        ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
        !           478:                                        ep->s2 = lenitem(ep);
        !           479:                                }
        !           480:                                else {
        !           481:                                        s_downi(ep, ep->s1/2);
        !           482:                                        ep->mode = ATEND;
        !           483:                                }
        !           484:                        }
        !           485:                        else if (fwidth(noderepr(tree(ep->focus))[0]) < 0) {
        !           486:                                s_downi(ep, ich); /* Undo up */
        !           487:                                return;
        !           488:                        }
        !           489:                        else
        !           490:                                ep->mode = ATBEGIN;
        !           491:                        continue;
        !           492: 
        !           493:                case ATEND:
        !           494:                        lastnnitem(ep);
        !           495:                        if (isunititem(ep)) {
        !           496:                                ep->s2 = lenitem(ep);
        !           497:                                ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
        !           498:                        }
        !           499:                        else
        !           500:                                s_downi(ep, ep->s1/2);
        !           501:                        continue;
        !           502: 
        !           503:                default:
        !           504:                        Abort();
        !           505: 
        !           506:                }
        !           507:        }
        !           508: }
        !           509: 
        !           510: 
        !           511: /*
        !           512:  * Safe up, downi, left and rite routines:
        !           513:  * 1) Rather die than fail;
        !           514:  * 2) Update ep->highest properly.
        !           515:  */
        !           516: 
        !           517: Visible Procedure
        !           518: s_up(ep)
        !           519:        register environ *ep;
        !           520: {
        !           521:        if (!up(&ep->focus))
        !           522:                syserr("s_up failed");
        !           523:        higher(ep);
        !           524: }
        !           525: 
        !           526: Visible Procedure
        !           527: s_downi(ep, i)
        !           528:        register environ *ep;
        !           529:        register int i;
        !           530: {
        !           531:        if (!downi(&ep->focus, i))
        !           532:                syserr("s_downi failed");
        !           533: }
        !           534: 
        !           535: Visible Procedure
        !           536: s_down(ep)
        !           537:        register environ *ep;
        !           538: {
        !           539:        if (!down(&ep->focus))
        !           540:                syserr("s_down failed");
        !           541: }
        !           542: 
        !           543: Visible Procedure
        !           544: s_downrite(ep)
        !           545:        register environ *ep;
        !           546: {
        !           547:        if (!downrite(&ep->focus))
        !           548:                syserr("s_downrite failed");
        !           549: }
        !           550: 
        !           551: Visible Procedure
        !           552: s_left(ep)
        !           553:        register environ *ep;
        !           554: {
        !           555:        register int ich = ichild(ep->focus);
        !           556: 
        !           557:        s_up(ep);
        !           558:        s_downi(ep, ich-1);
        !           559: }
        !           560: 
        !           561: Visible Procedure
        !           562: s_rite(ep)
        !           563:        register environ *ep;
        !           564: {
        !           565:        register int ich = ichild(ep->focus);
        !           566: 
        !           567:        s_up(ep);
        !           568:        s_downi(ep, ich+1);
        !           569: }
        !           570: 
        !           571: 
        !           572: /*
        !           573:  * Find next item in a subset, using ep->s1 as index.
        !           574:  * (This used to be less trivial, so it's still a subroutine rather than
        !           575:  * coded in-line or as a macro.)
        !           576:  */
        !           577: 
        !           578: Visible bool
        !           579: nextitem(ep)
        !           580:        register environ *ep;
        !           581: {
        !           582:        if (ep->s1 >= 2*nchildren(tree(ep->focus)) + 1)
        !           583:                return No; /* Already at last item */
        !           584:        ++ep->s1;
        !           585:        return Yes;
        !           586: }
        !           587: 
        !           588: 
        !           589: /*
        !           590:  * Ditto for previous.
        !           591:  */
        !           592: 
        !           593: Visible bool
        !           594: previtem(ep)
        !           595:        register environ *ep;
        !           596: {
        !           597:        if (ep->s1 <= 1
        !           598:                || ep->s1 == 2 && fwidth(noderepr(tree(ep->focus))[0]) < 0)
        !           599:                return No; /* Already at first item */
        !           600:        --ep->s1;
        !           601:        return Yes;
        !           602: }
        !           603: 
        !           604: 
        !           605: /*
        !           606:  * Test whether item ep->s1 is "small", i.e., fixed or varying text
        !           607:  * but not a whole subtree.
        !           608:  */
        !           609: 
        !           610: Visible bool
        !           611: isunititem(ep)
        !           612:        register environ *ep;
        !           613: {
        !           614:        return (ep->s1&1) || Type(child(tree(ep->focus), ep->s1/2)) == Tex;
        !           615: }
        !           616: 
        !           617: 
        !           618: /*
        !           619:  * Check for consistent mode information.
        !           620:  */
        !           621: 
        !           622: Visible bool
        !           623: checkep(ep)
        !           624:        register environ *ep;
        !           625: {
        !           626:        switch (ep->mode) {
        !           627: 
        !           628:        case FHOLE:
        !           629:                if (!(ep->s1&1))
        !           630:                        break;
        !           631:                if (ep->s2 < 0 || ep->s2 > lenitem(ep))
        !           632:                        break;
        !           633:                return Yes;
        !           634: 
        !           635:        case VHOLE:
        !           636:                if (!(ep->s1&1)) {
        !           637:                        if (Type(child(tree(ep->focus), ep->s1/2)) != Tex)
        !           638:                                break;
        !           639:                }
        !           640:                if (ep->s2 < 0 || ep->s2 > lenitem(ep))
        !           641:                        break;
        !           642:                return Yes;
        !           643: 
        !           644:        case SUBSET:
        !           645:                if (ep->s2 == ep->s1 && isunititem(ep) && lenitem(ep) <= 0)
        !           646:                        break;
        !           647:                return Yes;
        !           648: 
        !           649:        default:
        !           650:                return Yes;
        !           651: 
        !           652:        }
        !           653:        dbmess(ep);
        !           654:        return No;
        !           655: }
        !           656: 
        !           657: 
        !           658: /*
        !           659:  * Like {next,prev,first,last}item, but with empty items skipped
        !           660:  * (i.e., those with length <= 0).
        !           661:  */
        !           662: 
        !           663: Visible bool
        !           664: nextnnitem(ep)
        !           665:        register environ *ep;
        !           666: {
        !           667:        register int s1save = ep->s1;
        !           668: 
        !           669:        while (nextitem(ep)) {
        !           670:                if (lenitem(ep) != 0)
        !           671:                        return Yes;
        !           672:        }
        !           673:        ep->s1 = s1save;
        !           674:        return No;
        !           675: }
        !           676: 
        !           677: Visible bool
        !           678: prevnnitem(ep)
        !           679:        register environ *ep;
        !           680: {
        !           681:        register int s1save = ep->s1;
        !           682:        register int len;
        !           683: 
        !           684:        while (previtem(ep)) {
        !           685:                len = lenitem(ep);
        !           686:                if (len > 0 || len < 0 && ep->s1 > 1)
        !           687:                        return Yes;
        !           688:        }
        !           689:        ep->s1 = s1save;
        !           690:        return No;
        !           691: }
        !           692: 
        !           693: 
        !           694: Visible Procedure
        !           695: firstnnitem(ep)
        !           696:        register environ *ep;
        !           697: {
        !           698:        ep->s1 = fwidth(noderepr(tree(ep->focus))[0]) < 0 ? 2 : 1;
        !           699:        while (lenitem(ep) == 0) {
        !           700:                if (!nextitem(ep))
        !           701:                        break;
        !           702:        }
        !           703:        return;
        !           704: }
        !           705: 
        !           706: Visible Procedure
        !           707: lastnnitem(ep)
        !           708:        register environ *ep;
        !           709: {
        !           710:        ep->s1 = 2*nchildren(tree(ep->focus)) + 1;
        !           711:        while (lenitem(ep) == 0) {
        !           712:                if (!previtem(ep))
        !           713:                        break;
        !           714:        }
        !           715:        return;
        !           716: }
        !           717: 
        !           718: 
        !           719: /*
        !           720:  * Prepare the focus for insertion.
        !           721:  * If the focus isn't a hole, make a hole just before it which becomes the
        !           722:  * new focus.
        !           723:  * Also repair strange statuses left by moves, so we may have more chance
        !           724:  * to insert a character.
        !           725:  */
        !           726: 
        !           727: Visible Procedure
        !           728: fixit(ep)
        !           729:        register environ *ep;
        !           730: {
        !           731:        /* First, make a hole if it's not already a hole. */
        !           732: 
        !           733:        switch (ep->mode) {
        !           734: 
        !           735:        case FHOLE:
        !           736:                break;
        !           737: 
        !           738:        case VHOLE:
        !           739:                if (ep->s1&1)
        !           740:                        ep->mode = FHOLE;
        !           741:                break;
        !           742: 
        !           743:        case SUBRANGE:
        !           744:                if (ep->s1&1)
        !           745:                        ep->mode = FHOLE;
        !           746:                else
        !           747:                        ep->mode = VHOLE;
        !           748:                break;
        !           749: 
        !           750:        case SUBSET:
        !           751:                if (ep->s1&1) {
        !           752:                        if (ep->s1 == 1)
        !           753:                                ep->mode = ATBEGIN;
        !           754:                        else {
        !           755:                                ep->mode = FHOLE;
        !           756:                                ep->s2 = 0;
        !           757:                        }
        !           758:                }
        !           759:                else if (Type(child(tree(ep->focus), ep->s1/2)) == Tex) {
        !           760:                        ep->mode = VHOLE;
        !           761:                        ep->s2 = 0;
        !           762:                }
        !           763:                else {
        !           764:                        s_downi(ep, ep->s1/2);
        !           765:                        ep->mode = ATBEGIN;
        !           766:                }
        !           767:                break;
        !           768: 
        !           769:        case ATBEGIN:
        !           770:        case SUBLIST:
        !           771:        case WHOLE:
        !           772:                ep->mode = ATBEGIN;
        !           773:                break;
        !           774: 
        !           775:        case ATEND:
        !           776:                break;
        !           777: 
        !           778:        default:
        !           779:                Abort();
        !           780:        }
        !           781: 
        !           782:        leftvhole(ep);
        !           783:        if (ep->mode == ATEND && symbol(tree(ep->focus)) == Hole)
        !           784:                ep->mode = WHOLE; /***** Experiment! *****/
        !           785: }
        !           786: 
        !           787: 
        !           788: /*
        !           789:  * Small utility to see if a string contains only spaces
        !           790:  * (this is true for the empty string "").
        !           791:  * The string pointer must not be null!
        !           792:  */
        !           793: 
        !           794: Visible bool
        !           795: allspaces(str)
        !           796:        register string str;
        !           797: {
        !           798:        Assert(str);
        !           799:        for (; *str; ++str) {
        !           800:                if (*str != ' ')
        !           801:                        return No;
        !           802:        }
        !           803:        return Yes;
        !           804: }
        !           805: 
        !           806: 
        !           807: /*
        !           808:  * Function to compute the actual width of the focus.
        !           809:  */
        !           810: 
        !           811: Visible int
        !           812: focwidth(ep)
        !           813:        register environ *ep;
        !           814: {
        !           815:        node nn;
        !           816:        register node n = tree(ep->focus);
        !           817:        register string *rp = noderepr(n);
        !           818:        register int i;
        !           819:        register int w;
        !           820:        int len = 0;
        !           821: 
        !           822:        switch (ep->mode) {
        !           823: 
        !           824:        case VHOLE:
        !           825:        case FHOLE:
        !           826:        case ATEND:
        !           827:        case ATBEGIN:
        !           828:                return 0;
        !           829: 
        !           830:        case WHOLE:
        !           831:                return width(n);
        !           832: 
        !           833:        case SUBRANGE:
        !           834:                return ep->s3 - ep->s2 + 1;
        !           835: 
        !           836:        case SUBSET:
        !           837:                for (i = ep->s1; i <= ep->s2; ++i) {
        !           838:                        if (i&1)
        !           839:                                w = fwidth(rp[i/2]);
        !           840:                        else {
        !           841:                                nn = child(n, i/2);
        !           842:                                w = width(nn);
        !           843:                        }
        !           844:                        if (w < 0 && len >= 0)
        !           845:                                len = w;
        !           846:                        else if (w >= 0 && len < 0)
        !           847:                                ;
        !           848:                        else
        !           849:                                len += w;
        !           850:                }
        !           851:                return len;
        !           852: 
        !           853:        case SUBLIST:
        !           854:                len = width(n);
        !           855:                for (i = ep->s3; i > 0; --i)
        !           856:                        n = lastchild(n);
        !           857:                w = width(n);
        !           858:                if (w < 0 && len >= 0)
        !           859:                        return w;
        !           860:                if (w >= 0 && len < 0)
        !           861:                        return len;
        !           862:                return len - w;
        !           863: 
        !           864:        default:
        !           865:                Abort();
        !           866:                /* NOTREACHED */
        !           867:        }
        !           868: }
        !           869: 
        !           870: 
        !           871: /*
        !           872:  * Compute the offset of the focus from the beginning of the current node.
        !           873:  * This may be input again to fixfocus to allow restoration of this position.
        !           874:  */
        !           875: 
        !           876: Visible int
        !           877: focoffset(ep)
        !           878:        register environ *ep;
        !           879: {
        !           880:        node nn;
        !           881:        register node n;
        !           882:        register string *rp;
        !           883:        register int w;
        !           884:        register int len;
        !           885:        register int i;
        !           886: 
        !           887:        switch (ep->mode) {
        !           888: 
        !           889:        case WHOLE:
        !           890:        case SUBLIST:
        !           891:                return 0;
        !           892: 
        !           893:        case ATBEGIN:
        !           894:                return ep->spflag;
        !           895: 
        !           896:        case ATEND:
        !           897:                w = width(tree(ep->focus));
        !           898:                if (w < 0)
        !           899:                        return w;
        !           900:                return w + ep->spflag;
        !           901: 
        !           902:        case SUBSET:
        !           903:        case FHOLE:
        !           904:        case VHOLE:
        !           905:        case SUBRANGE:
        !           906:                n = tree(ep->focus);
        !           907:                rp = noderepr(n);
        !           908:                len = 0;
        !           909:                for (i = 1; i < ep->s1; ++i) {
        !           910:                        if (i&1)
        !           911:                                w = Fwidth(rp[i/2]);
        !           912:                        else {
        !           913:                                nn = child(n, i/2);
        !           914:                                w = width(nn);
        !           915:                        }
        !           916:                        if (w < 0) {
        !           917:                                if (len >= 0)
        !           918:                                        len = w;
        !           919:                                else
        !           920:                                        len += w;
        !           921:                        }
        !           922:                        else if (len >= 0)
        !           923:                                len += w;
        !           924:                }
        !           925:                if (ep->mode == SUBSET || len < 0)
        !           926:                        return len;
        !           927:                return len + ep->s2 + ep->spflag;
        !           928: 
        !           929:        default:
        !           930:                Abort();
        !           931:                /* NOTREACHED */
        !           932:        }
        !           933: }
        !           934: 
        !           935: 
        !           936: /*
        !           937:  * Return the first character of the focus (maybe '\n'; 0 if zero-width).
        !           938:  */
        !           939: 
        !           940: Visible int
        !           941: focchar(ep)
        !           942:        environ *ep;
        !           943: {
        !           944:        node n = tree(ep->focus);
        !           945:        string str;
        !           946:        string *rp;
        !           947:        int i;
        !           948:        int c;
        !           949: 
        !           950:        switch (ep->mode) {
        !           951: 
        !           952:        case VHOLE:
        !           953:        case FHOLE:
        !           954:        case ATBEGIN:
        !           955:        case ATEND:
        !           956:                return 0;
        !           957: 
        !           958:        case WHOLE:
        !           959:        case SUBLIST:
        !           960:                return nodechar(n);
        !           961: 
        !           962:        case SUBSET:
        !           963:                rp = noderepr(n);
        !           964:                for (i = ep->s1; i <= ep->s2; ++i) {
        !           965:                        if (i&1) {
        !           966:                                if (!Fw_zero(rp[i/2]))
        !           967:                                return rp[i/2][0];
        !           968:                        }
        !           969:                        else {
        !           970:                                c = nodechar(child(n, i/2));
        !           971:                                if (c)
        !           972:                                        return c;
        !           973:                        }
        !           974:                }
        !           975:                return 0;
        !           976: 
        !           977:        case SUBRANGE:
        !           978:                if (ep->s1&1)
        !           979:                        str = noderepr(n)[ep->s1/2];
        !           980:                else {
        !           981:                        Assert(Type(child(n, ep->s1/2)) == Tex);
        !           982:                        str = Str((value)child(n, ep->s1/2));
        !           983:                }
        !           984:                return str[ep->s2];
        !           985: 
        !           986:        default:
        !           987:                Abort();
        !           988:                /* NOTREACHED */
        !           989: 
        !           990:        }
        !           991: }
        !           992: 
        !           993: 
        !           994: /*
        !           995:  * Subroutine to return first character of node.
        !           996:  */
        !           997: 
        !           998: Visible int
        !           999: nodechar(n)
        !          1000:        node n;
        !          1001: {
        !          1002:        string *rp;
        !          1003:        int nch;
        !          1004:        int i;
        !          1005:        int c;
        !          1006: 
        !          1007:        if (Type(n) == Tex)
        !          1008:                return Str((value)n)[0];
        !          1009:        rp = noderepr(n);
        !          1010:        if (!Fw_zero(rp[0]))
        !          1011:                return rp[0][0];
        !          1012:        nch = nchildren(n);
        !          1013:        for (i = 1; i <= nch; ++i) {
        !          1014:                c = nodechar(child(n, i));
        !          1015:                if (c)
        !          1016:                        return c;
        !          1017:                if (!Fw_zero(rp[i]))
        !          1018:                        return rp[i][0];
        !          1019:        }
        !          1020:        return 0;
        !          1021: }
        !          1022: 
        !          1023: 
        !          1024: /*
        !          1025:  * Function to compute the actual indentation level at the focus.
        !          1026:  */
        !          1027: 
        !          1028: Visible int
        !          1029: focindent(ep)
        !          1030:        environ *ep;
        !          1031: {
        !          1032:        int y = Ycoord(ep->focus);
        !          1033:        int x = Xcoord(ep->focus);
        !          1034:        int level = Level(ep->focus);
        !          1035:        node n = tree(ep->focus);
        !          1036: 
        !          1037:        switch (ep->mode) {
        !          1038: 
        !          1039:        case WHOLE:
        !          1040:        case ATBEGIN:
        !          1041:        case SUBLIST:
        !          1042:                break;
        !          1043: 
        !          1044:        case ATEND:
        !          1045:                evalcoord(n, 1 + nchildren(n), &y, &x, &level);
        !          1046:                break;
        !          1047: 
        !          1048:        case SUBSET:
        !          1049:        case FHOLE:
        !          1050:        case VHOLE:
        !          1051:                evalcoord(n, ep->s1/2, &y, &x, &level);
        !          1052:                break;
        !          1053: 
        !          1054:        default:
        !          1055:                Abort();
        !          1056:        }
        !          1057:        return level;
        !          1058: }
        !          1059: 
        !          1060: 
        !          1061: /*
        !          1062:  * Routines to move 'environ' structures.
        !          1063:  */
        !          1064: 
        !          1065: emove(s, d)
        !          1066:        environ *s;
        !          1067:        environ *d;
        !          1068: {
        !          1069: #ifdef STRUCTASS
        !          1070:        *d = *s;
        !          1071: #else !STRUCTASS
        !          1072:        d->focus = s->focus;
        !          1073: 
        !          1074:        d->mode = s->mode;
        !          1075:        d->copyflag = s->copyflag;
        !          1076:        d->spflag = s->spflag;
        !          1077:        d->changed = s->changed;
        !          1078: 
        !          1079:        d->s1 = s->s1;
        !          1080:        d->s2 = s->s2;
        !          1081:        d->s3 = s->s3;
        !          1082: 
        !          1083:        d->highest = s->highest;
        !          1084: 
        !          1085:        d->copybuffer = s->copybuffer;
        !          1086: #ifdef RECORDING
        !          1087:        d->oldmacro = s->oldmacro;
        !          1088:        d->newmacro = s->newmacro;
        !          1089: #endif RECORDING
        !          1090: 
        !          1091:        d->generation = s->generation;
        !          1092: #endif !STRUCTASS
        !          1093: }
        !          1094: 
        !          1095: ecopy(s, d)
        !          1096:        environ *s;
        !          1097:        environ *d;
        !          1098: {
        !          1099:        emove(s, d);
        !          1100:        pathcopy(d->focus);
        !          1101:        copy(d->copybuffer);
        !          1102: #ifdef RECORDING
        !          1103:        copy(d->oldmacro);
        !          1104:        copy(d->newmacro);
        !          1105: #endif RECORDING
        !          1106: }
        !          1107: 
        !          1108: erelease(e)
        !          1109:        environ *e;
        !          1110: {
        !          1111:        pathrelease(e->focus);
        !          1112:        release(e->copybuffer);
        !          1113: #ifdef RECORDING
        !          1114:        release(e->oldmacro);
        !          1115:        release(e->newmacro);
        !          1116: #endif RECORDING
        !          1117: }

unix.superglobalmegacorp.com

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