1 #ifndef lint
2 static char sccsid[] = "@(#)text.c	2.2 (CWI) 87/04/01";
3 #endif lint
4 #include "e.h"
5 #include "y.tab.h"
6 #include <ctype.h>
7 
8 #define	CSSIZE	400
9 char	cs[CSSIZE+20];	/* text string converted into this */
10 char	*csp;		/* next spot in cs[] */
11 char	*psp;		/* next character in input token */
12 
13 int	lf, rf;		/* temporary spots for left and right fonts */
14 int	lastft;		/* last \f added */
15 int	nextft;		/* next \f to be added */
16 
17 text(t, p1)	/* convert text string p1 of type t */
18 	int t;
19 	char *p1;
20 {
21 	int c;
22 	char *p;
23 	tbl *tp;
24 
25 	yyval = salloc();
26 	ebase[yyval] = 0;
27 	eht[yyval] = EM(1.0, ps);	/* ht in ems of orig size */
28 	eps[yyval] = ps;
29 	lfont[yyval] = rfont[yyval] = ROM;
30 	if (t == QTEXT) {
31 		for (p = p1; *p; p++)	/* scan for embedded \f's */
32 			if (*p == '\\' && *(p+1) == 'f')
33 				break;
34 		if (*p)		/* if found \f, leave it alone and hope */
35 			p = p1;
36 		else {
37 			sprintf(cs, "\\f%s%s\\fP", ftp->name, p1);
38 			p = cs;
39 		}
40 	} else if (t == SPACE)
41 		p = "\\ ";
42 	else if (t == THIN)
43 		p = "\\|";
44 	else if (t == TAB)
45 		p = "\\t";
46 	else if ((tp = lookup(restbl, p1, NULL)) != NULL) {
47 		p = tp->defn;
48 	} else {
49 		lf = rf = 0;
50 		/* sprintf(cs, "\\f%s", ftp->name); */
51 		lastft = 0;
52 		csp = cs;
53 		for (psp = p1; (c = *psp++) != '\0'; ) {
54 			nextft = ft;
55 			rf = trans(c, p1);
56 			if (lf == 0)
57 				lf = rf;	/* save first */
58 			if (csp-cs > CSSIZE)
59 				error(FATAL,"converted token %.25s... too long",p1);
60 		}
61 		sadd("\\fP");
62 		*csp = '\0';
63 		p = cs;
64 		lfont[yyval] = lf;
65 		rfont[yyval] = rf;
66 	}
67 	dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n",
68 		t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval], ps);
69 	printf(".ds %d \"%s\n", yyval, p);
70 }
71 
72 trans(c, p1)
73 	int c;
74 	char *p1;
75 {
76 	int f;
77 
78 	f = ROM;
79 	switch (c) {
80 	case '0': case '1': case '2': case '3': case '4':
81 	case '5': case '6': case '7': case '8': case '9':
82 	case ':': case ';': case '!': case '%': case '?':
83 	case '(': case '[': case ']':
84 		if (rf == ITAL)
85 			shim();
86 		roman(c);
87 		break;
88 	case ')':
89 		if (rf == ITAL)
90 			halfshim();
91 		roman(c);
92 		break;
93 	case ',':
94 		roman(c);
95 		halfshim();
96 		f = rf;
97 		break;
98 	case '.':
99 		if (rf == ROM)
100 			roman(c);
101 		else
102 			cadd(c);
103 		f = rf;
104 		break;
105 	case '|':
106 		if (rf == ITAL && ttype != DEV202)
107 			shim();
108 		shim(); roman(c); shim();
109 		break;
110 	case '=':
111 		if (rf == ITAL)
112 			shim();
113 		name4('e','q');
114 		break;
115 	case '+':
116 		if (rf == ITAL)
117 			shim();
118 		name4('p','l');
119 		break;
120 	case '>': case '<':
121 		if (rf == ITAL)
122 			shim();
123 		if (*psp == '=') {	/* look ahead for == <= >= */
124 			name4(c,'=');
125 			psp++;
126 		} else {
127 			cadd(c);
128 		}
129 		break;
130 	case '-':
131 		if (rf == ITAL)
132 			shim();
133 		if (*psp == '>') {
134 			name4('-','>');
135 			halfshim();
136 			psp++;
137 		} else {
138 			name4('m','i');
139 		}
140 		break;
141 	case '/':
142 		halfshim();
143 		cadd('/');
144 		halfshim();
145 		break;
146 	case '~': case ' ':
147 		shim(); shim();
148 		break;
149 	case '^':
150 		shim();
151 		break;
152 	case '\\':	/* troff - pass only \(xx without comment */
153 		if (rf == ITAL)
154 			shim();
155 		cadd('\\');
156 		cadd(c = *psp++);
157 		if (c == '(' && *psp && *(psp+1)) {
158 			cadd(*psp++);
159 			cadd(*psp++);
160 		} else
161 			fprintf(stderr, "eqn warning: unquoted troff command \\%c, line %d, file %s\n",
162 				c, curfile->lineno, curfile->fname);
163 		break;
164 	case '\'':
165 		name4('f','m');
166 		break;
167 
168 	case 'f':
169 		if (ft == ITAL) {
170 			if (psp == p1+1 || !isalnum(*(psp-2)))
171 				halfshim();
172 			cadd('f');
173 			if (!isalpha(*psp) && *psp != '\0')	/* add \| except in text */
174 				shim();
175 			f = ITAL;
176 		}
177 		else
178 			cadd('f');
179 		break;
180 	case 'j':
181 		if (ft == ITAL) {
182 			sadd("\\^j");
183 			f = ITAL;
184 		}
185 		else
186 			cadd('j');
187 		break;
188 	default:
189 		cadd(c);
190 		f = ft==ITAL ? ITAL : ROM;
191 		break;
192 	}
193 	return(f);
194 }
195 
196 shim()	/* add a \| space */
197 {
198 	sadd("\\|");
199 }
200 
201 halfshim()	/* add a \^ space */
202 {
203 	sadd("\\^");
204 }
205 
206 roman(c)	/* add char c in "roman" font */
207 	int c;
208 {
209 	nextft = ROM;
210 	cadd(c);
211 }
212 
213 name4(c1,c2)
214 	int c1, c2;
215 {
216 	sadd("\\(");
217 	cadd(c1);
218 	cadd(c2);
219 }
220 
221 sadd(s)		/* add string s to cs */
222 	char *s;
223 {
224 	while (*s)
225 		cadd(*s++);
226 }
227 
228 cadd(c)		/* add char c to end of cs */
229 	int c;
230 {
231 	char *p;
232 
233 	if (lastft != nextft) {
234 		if (lastft != 0) {
235 			*csp++ = '\\';
236 			*csp++ = 'f';
237 			*csp++ = 'P';
238 		}
239 		*csp++ = '\\';
240 		*csp++ = 'f';
241 		if (ftp == ftstack) {	/* bottom level */
242 			if (ftp->ft == ITAL)	/* usual case */
243 				*csp++ = nextft;
244 			else		/* gfont set, use it */
245 				for (p = ftp->name; *csp = *p++; )
246 					csp++;
247 		} else {	/* inside some kind of font ... */
248 			for (p = ftp->name; *csp = *p++; )
249 				csp++;
250 		}
251 		lastft = nextft;
252 	}
253 	*csp++ = c;
254 }
255