Annotation of researchv10no/cmd/picasso/troffgen.c, revision 1.1

1.1     ! root        1: /*     Copyright (c) 1988 AT&T */
        !             2: /*       All Rights Reserved   */
        !             3: 
        !             4: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
        !             5: /*     The copyright notice above does not evidence any        */
        !             6: /*     actual or intended publication of such source code.     */
        !             7: 
        !             8: /*     @(#)picasso:troffgen.c  1.0     */
        !             9: 
        !            10: #include <string.h>
        !            11: #include <ctype.h>
        !            12: #include "font.h"
        !            13: #include "picasso.h"
        !            14: #include "y.tab.h"
        !            15: 
        !            16: char   esc         = '\\';
        !            17: char   eqn_delim[] = "\0";
        !            18: 
        !            19: /* the following table of troff names for special characters is in ASCII   */
        !            20: /* order of their names, so that a binary search could be done if desired. */
        !            21: /* the font field MUST conform to the font initialization in fonts.c, with */
        !            22: /* the "standard" Times Roman in position 0 and the symbol font as font 1. */
        !            23: 
        !            24: struct trcode  {char name[2];  char font;  unsigned char value;}
        !            25:        trcode[]  =
        !            26:                {'\0','\0','\0','\0',           /* null entry, never matched. */
        !            27:                '!','=', 1, 0271,               /* not equal */
        !            28:                '!','b', 1, 0313,               /* not subset */
        !            29:                '!','m', 1, 0317,               /* not member */
        !            30:                '"','a', 0, 0315,               /* hungarumlaut accent */
        !            31:                '\'','\'',0,0272,               /* right double quote */
        !            32:                '*','*', 1, '*',                /* math star */
        !            33: 
        !            34:                '*','A', 1, 'A', '*','B', 1, 'B', '*','C', 1, 'X',   /* greek */
        !            35:                '*','D', 1, 'D', '*','E', 1, 'E', '*','F', 1, 'F',   /* alpha-*/
        !            36:                '*','G', 1, 'G', '*','H', 1, 'Q', '*','I', 1, 'I',   /* bet.  */
        !            37:                '*','K', 1, 'K', '*','L', 1, 'L', '*','M', 1, 'M',
        !            38:                '*','N', 1, 'N', '*','O', 1, 'O', '*','P', 1, 'P',
        !            39:                '*','Q', 1, 'Y', '*','R', 1, 'R', '*','S', 1, 'S',
        !            40:                '*','T', 1, 'T', '*','U', 1, 'U', '*','W', 1, 'W',
        !            41:                '*','X', 1, 'C', '*','Y', 1, 'H', '*','Z', 1, 'Z',
        !            42:                '*','a', 1, 'a', '*','b', 1, 'b', '*','c', 1, 'x',
        !            43:                '*','d', 1, 'd', '*','e', 1, 'e', '*','f', 1, 'f',
        !            44:                '*','g', 1, 'g', '*','h', 1, 'q', '*','i', 1, 'i',
        !            45:                '*','k', 1, 'k', '*','l', 1, 'l', '*','m', 1, 'm',
        !            46:                '*','n', 1, 'n', '*','o', 1, 'o', '*','p', 1, 'p',
        !            47:                '*','q', 1, 'y', '*','r', 1, 'r', '*','s', 1, 's',
        !            48:                '*','t', 1, 't', '*','u', 1, 'u', '*','w', 1, 'w',
        !            49:                '*','x', 1, 'c', '*','y', 1, 'h', '*','z', 1, 'z',
        !            50: 
        !            51:                '+','-', 1, 0261,               /* plus-minus */
        !            52:                ',','a', 0, 0313,               /* cedilla accent */
        !            53:                '-','>', 1, 0256,               /* right arrow */
        !            54:                '-','a', 0, 0305,               /* macron accent */
        !            55:                '.','a', 0, 0307,               /* dot accent */
        !            56:                ':','a', 0, 0310,               /* dieresis accent */
        !            57:                '<','-', 1, 0254,               /* left arrow */
        !            58:                '<','=', 1, 0243,               /* less than or equal */
        !            59:                '=','=', 1, 0272,               /* identically equal */
        !            60:                '>','=', 1, 0263,               /* greater than or equal */
        !            61:                'C','O', 1, 0343,               /* copyright (sanserif) */
        !            62:                'C','R', 1, 0277,               /* carriage return */
        !            63:                'C','a', 0, 0316,               /* ogonek accent */
        !            64:                'I','f', 1, 0301,               /* I (fraktur) */
        !            65:                'L','B', 1, 0350,               /* paren, left bottom */
        !            66:                'L','T', 1, 0346,               /* paren, left top */
        !            67:                'O','+', 1, 0305,               /* circled plus */
        !            68:                'O','x', 1, 0304,               /* circled times */
        !            69:                'R','B', 1, 0370,               /* paren, right bottom */
        !            70:                'R','G', 1, 0342,               /* registered (sanserif) */
        !            71:                'R','T', 1, 0366,               /* paren, right top */
        !            72:                'R','f', 1, 0302,               /* R (fraktur) */
        !            73:                'T','M', 1, 0344,               /* trademark (sanserif) */
        !            74:                'U','a', 0, 0306,               /* breve accent */
        !            75:                '^','a', 0, 0303,               /* circumflex accent */
        !            76:                '`','`', 0, 0252,               /* left double quote */
        !            77:                'a','a', 0, 0302,               /* circumflex accent */
        !            78:                'a','b', 1, 0253,               /* arrow both (left & right) */
        !            79:                'a','f', 1, 0300,               /* aleph */
        !            80:                'a','h', 1, 0276,               /* arrow horizontal extender */
        !            81:                'a','n', 1, 0320,               /* angle */
        !            82:                'a','p', 1, '~',                /* approximates */
        !            83:                'a','v', 1, 0275,               /* arrow vertical extender */
        !            84:                'b','<', 1, 0341,               /* left angle bracket */
        !            85:                'b','>', 1, 0361,               /* right angle bracket */
        !            86:                'b','u', 0, 0267,               /* bullet */
        !            87:                'b','v', 1, 0352,               /* bold vertical (extender) */
        !            88:                'c','.', 1, 0327,               /* centered dot */
        !            89:                'c','a', 1, 0307,               /* cap */
        !            90:                'c','g', 1, '@',                /* congruent to */
        !            91:                'c','o', 1, 0323,               /* copyright (serif) */
        !            92:                'c','r', 0, 0250,               /* currency */
        !            93:                'c','t', 0, 0242,               /* cent */
        !            94:                'c','u', 1, 0310,               /* cup */
        !            95:                'd','a', 1, 0257,               /* down arrow */
        !            96:                'd','d', 0, 0263,               /* double dagger */
        !            97:                'd','e', 1, 0260,               /* degree */
        !            98:                'd','g', 0, 0262,               /* dagger */
        !            99:                'd','i', 1, 0270,               /* divide */
        !           100:                'e','l', 0, 0274,               /* ellipsis */
        !           101:                'e','m', 0, 0320,               /* emdash */
        !           102:                'e','n', 0, 0261,               /* endash */
        !           103:                'e','q', 1, '=',                /* equals */
        !           104:                'e','s', 1, 0306,               /* empty set */
        !           105:                'f','a', 1, '"',                /* for all */
        !           106:                'f','i', 0, 0256,               /* fi ligature */
        !           107:                'f','l', 0, 0257,               /* fl ligature */
        !           108:                'f','m', 1, 0242,               /* minute (footmark) */
        !           109:                'f','n', 0, 0246,               /* florin */
        !           110:                'f','r', 0, 0244,               /* fraction bar */
        !           111:                'g','a', 0, 0301,               /* circumflex accent */
        !           112:                'g','r', 1, 0321,               /* gradient */
        !           113:                'h','y', 0, '-',                /* hyphen */
        !           114:                'i','b', 1, 0315,               /* improper subset  */
        !           115:                'i','f', 1, 0245,               /* infinity */
        !           116:                'i','p', 1, 0312,               /* improper superset */
        !           117:                'i','s', 1, 0362,               /* integral sign */
        !           118:                'l','&', 1, 0331,               /* logical and */
        !           119:                'l','b', 1, 0356,               /* brace, left bottom */
        !           120:                'l','c', 1, 0351,               /* square bracket l. ceiling */
        !           121:                'l','f', 1, 0353,               /* square bracket l. floor */
        !           122:                'l','k', 1, 0355,               /* brace, left middle */
        !           123:                'l','t', 1, 0354,               /* brace, left top */
        !           124:                'l','z', 1, 0340,               /* lozenge */
        !           125:                'l','|', 1, 0332,               /* logical or */
        !           126:                'm','i', 1, '-',                /* minus */
        !           127:                'm','o', 1, 0316,               /* member of */
        !           128:                'm','u', 1, 0264,               /* multiply */
        !           129:                'n','o', 1, 0330,               /* logical not */
        !           130:                'o','a', 0, 0312,               /* ring accent */
        !           131:                'o','r', 1, '|',                /* or (vertical bar) */
        !           132:                'p','d', 1, 0266,               /* partial derivative */
        !           133:                'p','g', 0, 0266,               /* paragraph */
        !           134:                'p','l', 1, '+',                /* plus */
        !           135:                'p','p', 1, '^',                /* perpendicular */
        !           136:                'p','s', 0, 0243,               /* pound sterling */
        !           137:                'p','t', 1, 0265,               /* proportional to */
        !           138:                'r','b', 1, 0376,               /* brace, right bottom */
        !           139:                'r','c', 1, 0371,               /* square bracket r. ceiling */
        !           140:                'r','f', 1, 0373,               /* square bracket r. floor */
        !           141:                'r','g', 1, 0322,               /* registered (serif) */
        !           142:                'r','k', 1, 0375,               /* brace, right middle */
        !           143:                'r','n', 1, '\'',               /* root extender (en) */
        !           144:                'r','t', 1, 0374,               /* brace, right top */
        !           145:                's','b', 1, 0314,               /* subset */
        !           146:                's','c', 0, 0247,               /* section */
        !           147:                's','l', 1, '/',                /* slash */
        !           148:                's','p', 1, 0311,               /* superset */
        !           149:                's','r', 1, 0326,               /* square root */
        !           150:                's','t', 1, '`',                /* such that */
        !           151:                't','e', 1, '$',                /* there exists */
        !           152:                't','f', 1, '\\',               /* therefore */
        !           153:                't','m', 1, 0324,               /* trademark (serif) */
        !           154:                't','s', 1, 'V',                /* terminal sigma */
        !           155:                'u','a', 1, 0255,               /* up arrow */
        !           156:                'u','l', 1, '_',                /* underscore */
        !           157:                'v','a', 0, 0317,               /* caron accent */
        !           158:                'w','s', 1, 0303,               /* Weierstrass P */
        !           159:                'y','n', 0, 0245,               /* yen */
        !           160:                '~','a', 0, 0304,               /* tilde accent */
        !           161:                '~','~', 1, 0273,               /* approximately */
        !           162: 
        !           163:                '\0','\0','\0','\0',            /* sentinel; loop terminus */
        !           164:                };
        !           165: 
        !           166: int    troffcode(str)
        !           167:        char    *str;
        !           168: {
        !           169:        int     n;
        !           170: 
        !           171:        for (n = 1; trcode[n].name[0] != '\0'; n++)
        !           172:                if (str[0] == trcode[n].name[0] && str[1] == trcode[n].name[1])
        !           173:                        return n;
        !           174:        return 0;
        !           175: }
        !           176: 
        !           177: static
        !           178: troffparm(name, parm, prev)
        !           179:        char    *name, *parm;
        !           180:        int     *prev;                  /* the previous value */
        !           181: {
        !           182: extern double  atof();
        !           183:        double  r, s=0, t;
        !           184: 
        !           185:        while (isspace(*parm))
        !           186:                ++parm;
        !           187:        t = getfval(name);
        !           188:        if (*parm == '\0')
        !           189:                r = *prev;
        !           190:        else {
        !           191:                r = atof(parm);
        !           192:                if (*parm == '+' || *parm == '-')
        !           193:                        s = t;
        !           194:                while (*parm && !isspace(*parm))
        !           195:                        parm++;
        !           196:                switch (parm[-1]) {
        !           197:                        case 'i':       r *= 72;                break;
        !           198:                        case 'c':       r *= (72.*50./127.);    break;
        !           199:                        case 'P':       r *= 12;                break;
        !           200:                        case 'u':       r /= 6;                 break;
        !           201:                }
        !           202:        }
        !           203:        *prev = t;
        !           204:        setfval(name, r+s);
        !           205: }
        !           206: 
        !           207: /* The following should be regarded as a kludge, since these values don't
        !           208: get set by textsize = , etc.  There is confusion between picasso's ideas
        !           209: of these variables and troff's. */
        !           210: static int     ft;             /* save previous font for \fP and .ft */
        !           211: static int     psize = 10,     /* ditto previous point size */
        !           212:                vsize = 12;     /*    and vertical spacing */
        !           213: 
        !           214: troff(s)
        !           215:        char    *s;
        !           216: {
        !           217:        int     i, fp;
        !           218: 
        !           219:        if (s[1] == 'f' && s[2] == 't') {
        !           220:                for (s += 3; isspace(*s); ++s)
        !           221:                        ;
        !           222:                i = getfval("textfont");        /* save current font */
        !           223:                if (s == '\0')                  /* reset previous */
        !           224:                        fp = ft;
        !           225:                else if (isdigit(*s))           /* allow multi-digit nums */
        !           226:                        fp = checkfont((double)atoi(s));
        !           227:                else
        !           228:                        fp = setfont(tostring(s));
        !           229:                ft = i;
        !           230:                setfval("textfont", fp);
        !           231:        }
        !           232:        else if (s[1] == 'p' && s[2] == 's')
        !           233:                troffparm("textsize", s+3, &psize);
        !           234:        else if (s[1] == 'v' && s[2] == 's')
        !           235:                troffparm("textspace", s+3, &vsize);
        !           236:        else if (s[1] == 'e')
        !           237:                if (s[2] == 'o')
        !           238:                        esc = '\0';
        !           239:                else if (s[2] == 'c') {
        !           240:                        for (s += 3; isspace(*s); ++s)
        !           241:                                ;
        !           242:                        esc = *s ? *s : '\\';
        !           243:                }
        !           244: }
        !           245: 
        !           246: obj    *troffgen(s)
        !           247:        YYSTYPE s;
        !           248: {
        !           249:        troff(s.p);
        !           250:        save_one(CENTER, 0, 0, 0, s.p);
        !           251:        free(s.p);
        !           252:        return makenode(TROFF, 0, (int)getfval("curlayer"));
        !           253: }
        !           254: 
        !           255: char   *parse_text (txt, fp, sp)       /* split txt into substrings with */
        !           256:        char    *txt;                   /* uniform font and pointsize;    */
        !           257:        int     *fp, *sp;               /* some '\0' chars are put in txt.*/
        !           258: {
        !           259:        extern int  parsing;
        !           260: static char    buf[256];
        !           261: static int     n   = 0,
        !           262:                lim = 0;
        !           263:        int     i, j;
        !           264:        char    *bp;
        !           265: 
        !           266:        if (n == 0) {   /* new string; initialize */
        !           267:                lim = strlen(txt);
        !           268:                ft = *fp;
        !           269:        }
        !           270:        else if (n == lim) {
        !           271:                n = 0;
        !           272:                return NULL;
        !           273:        }
        !           274:        for (bp = buf; n < lim; ) {
        !           275:                if (txt[n] != esc && txt[n] != *eqn_delim)
        !           276:                        *bp++ = txt[n++];
        !           277:                else if (txt[n] == *eqn_delim) {
        !           278:                        if (!parsing) {
        !           279:                                do n++;
        !           280:                                while (txt[n] != eqn_delim[1] && n < lim);
        !           281:                                n++;
        !           282:                                continue;
        !           283:                        }
        !           284:                        if (bp > buf) { *bp = '\0'; return buf; }
        !           285:                        eqn_save(".EQ");
        !           286:                        while (txt[++n] != eqn_delim[1] && n < lim)
        !           287:                                *bp++ = txt[n];
        !           288:                        if (n < lim)
        !           289:                                ++n;
        !           290:                        strcpy(bp, "\n.EN");
        !           291:                        eqn_save(buf);
        !           292:                        eqn_gen(TEXT);
        !           293:                        bp = buf;
        !           294:                        *bp++ = '\0';   /* fudge, to prevent a 2nd save_one() */
        !           295:                }
        !           296:                else {                          /* fonts, sizes, troff codes  */
        !           297:                        switch (txt[n+1]) {
        !           298:                        default:
        !           299:                                *bp++ = txt[n++];
        !           300:                                break;
        !           301:                        case '&':               /* zero-width char */
        !           302:                                n += 2;         /* discard it */
        !           303:                                break;
        !           304:                        case '(':
        !           305:                                if ((i = troffcode(txt+n+2)) == 0)
        !           306:                                        *bp++ = txt[n++];       /* unknown */
        !           307:                                else {
        !           308:                                        if (bp > buf && *fp != trcode[i].font)
        !           309:                                                { *bp = '\0'; return buf; }
        !           310:                                        *bp++ = trcode[i].value;
        !           311:                                        ft = *fp;
        !           312:                                        *fp = trcode[i].font;
        !           313:                                        txt[++n] = '\\';
        !           314:                                        txt[n+1] = 'f';
        !           315:                                        txt[n+2] = 'P'; /* restore old font */
        !           316:                                }
        !           317:                                break;
        !           318:                        case 'N':
        !           319:                                n += 3;
        !           320:                                *bp++ = atoi(txt+n);
        !           321:                                while (isdigit(txt[n])) n++;
        !           322:                                break;
        !           323:                        case 'f':
        !           324:                                if (bp > buf) { *bp = '\0'; return buf; }
        !           325:                                n += 2;
        !           326:                                i = *fp;                /* save current font */
        !           327:                                if (txt[n] == 'P') {    /* reset previous */
        !           328:                                        *fp = ft;
        !           329:                                        ++n;
        !           330:                                }
        !           331:                                else if (isdigit(txt[n]))
        !           332:                                        *fp = checkfont((double)(txt[n++]-'0'));
        !           333:                                else {
        !           334:                                        if (txt[n] != '(')
        !           335:                                                *bp++ = txt[n++];
        !           336:                                        else {
        !           337:                                                *bp++ = txt[++n];
        !           338:                                                *bp++ = txt[++n];
        !           339:                                                ++n;
        !           340:                                        }
        !           341:                                        *bp = '\0';
        !           342:                                        *fp = setfont(tostring(bp=buf));
        !           343:                                }
        !           344:                                ft = i;
        !           345:                                break;
        !           346:                        case 's':
        !           347:                                if (bp > buf) { *bp = '\0'; return buf; }
        !           348:                                n += 2;
        !           349:                                if (txt[n] == '+' || txt[n] == '-') {
        !           350:                                        if ((i = *sp) == 0)
        !           351:                                                i = getfval("textsize");
        !           352:                                        if (txt[n] == '-')
        !           353:                                                i = -i;
        !           354:                                        ++n;
        !           355:                                }
        !           356:                                else
        !           357:                                        i = 0; 
        !           358:                                j = 0;
        !           359:                                if (i == 0 && txt[n] == '0'){/* use previous */
        !           360:                                        i = psize;
        !           361:                                        ++n;
        !           362:                                }
        !           363:                                else {
        !           364:                                        if (isdigit(txt[n]))
        !           365:                                                j = txt[n++] - '0';
        !           366:                                        if (j && isdigit(txt[n]))
        !           367:                                                j = j * 10 + txt[n++] - '0';
        !           368:                                }
        !           369:                                psize = *sp = (i < 0 ? -(i+j) : i+j);
        !           370:                                break;
        !           371:                        }
        !           372:                }
        !           373:        }
        !           374:        *bp = '\0';
        !           375:        if (bp != buf)
        !           376:                return buf;
        !           377:        else {
        !           378:                n = 0;
        !           379:                return NULL;
        !           380:        }
        !           381: }
        !           382: 
        !           383: int    eqn_count         = 0;
        !           384: char   psfname[L_tmpnam] = "";
        !           385: char   dpost[] = "dpost";
        !           386: FILE   *eqnfp  = NULL,
        !           387:        *pipefp = NULL;
        !           388: int    no_eqn = 0;
        !           389: 
        !           390: eqn_save(s)
        !           391:        char    *s;
        !           392: {
        !           393: extern char    *gwblib;
        !           394:        char    *dp, private[64], buf[BUFSIZ];
        !           395: 
        !           396:        if (pipefp == NULL && !no_eqn){/* open up eqn|troff|dpost subprocess */
        !           397:                if (access("/usr/bin/eqn", 1))  /* kludge! */
        !           398:                        no_eqn = 1;
        !           399:                else {
        !           400:                        sprintf(private, "%s/%s", gwblib, dpost);
        !           401:                        dp = access(private,1) ? dpost : private;
        !           402:                        tmpnam(psfname);
        !           403:                        sprintf(buf, "eqn|troff -Tpost|%s -B>%s", dp, psfname);
        !           404:                        if ((pipefp = popen(buf, "w")) == NULL)
        !           405:                                fatal("cannot pipe through eqn");
        !           406:                }
        !           407:        }
        !           408:        if (no_eqn) {
        !           409:                if (strncmp(s, ".EQ", 3) == 0 || strncmp(s, ".EN", 3) == 0 ||
        !           410:                                        strncmp(s, "delim", 5) == 0)
        !           411:                        ;
        !           412:                else
        !           413:                        savetext(CENTER, s);
        !           414:                return;
        !           415:        }
        !           416:        if (s[0] == '.' && s[1] == 'E' && s[2] == 'Q') {
        !           417:                double  f = getfval("textfont");
        !           418:                sprintf(buf,".ft %s\n.ps %d\n.vs %d\n", mount[(int)f]->name,
        !           419:                        (int)getfval("textsize"), (int)getfval("textspace"));
        !           420:                fputs(buf, pipefp);
        !           421:        }
        !           422:        fputs(s, pipefp);
        !           423:        fputc('\n', pipefp);
        !           424:        scan_delim(s);
        !           425: }
        !           426: 
        !           427: scan_delim(s)
        !           428:        char    *s;
        !           429: {
        !           430:        while (isspace(*s))
        !           431:                ++s;
        !           432:        /* probably eqn's syntax is less restrictive than the following */
        !           433:        if (strncmp(s,"delim",5)==0) {
        !           434:                for (s += 5; isspace(*s); ++s)
        !           435:                        ;
        !           436:                if (strcmp(s,"off")==0)
        !           437:                        eqn_delim[1] = eqn_delim[0] = '\0';
        !           438:                else {
        !           439:                        eqn_delim[1] = eqn_delim[0] = *s;
        !           440:                        if (*s++)
        !           441:                                if (*s)
        !           442:                                        eqn_delim[1] = *s;
        !           443:                }
        !           444:        }
        !           445: }
        !           446: 
        !           447: eqn_gen(type)
        !           448:        int     type;
        !           449: {
        !           450: extern int     ntextlines;
        !           451:        obj     *p;
        !           452:        char    buf[8];
        !           453: 
        !           454:        if (!no_eqn) {
        !           455:                fputs(".bp\n", pipefp);
        !           456:                sprintf(buf, "%d", ++eqn_count);
        !           457:                save_one(EQNTXT, 0, 0, ntextlines, buf);
        !           458:        }
        !           459:        if (type == TROFF) {
        !           460:                p = makenode(TROFF, 0, (int)getfval("curlayer"));
        !           461:                checktextcolor(p);
        !           462:                codegen = 1;
        !           463:        }
        !           464: }

unix.superglobalmegacorp.com

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