|
|
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.