|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.