Annotation of 43BSD/contrib/B/src/bed/supr.c, revision 1.1.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.