Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "e.h"
2
#include "y.tab.h"
3
#include <ctype.h>
4
#include <utf.h>
5
 
6
#define	CSSIZE	1000
7
char	cs[CSSIZE+20];	/* text string converted into this */
8
char	*csp;		/* next spot in cs[] */
9
char	*psp;		/* next character in input token */
10
 
11
int	lf, rf;		/* temporary spots for left and right fonts */
12
int	lastft;		/* last \f added */
13
int	nextft;		/* next \f to be added */
14
 
15
int	pclass;		/* class of previous character */
16
int	nclass;		/* class of next character */
17
 
18
int class[LAST][LAST] ={	/* guesswork, tuned to times roman postscript */
19
 
20
	/*OT OL IL DG LP RP SL PL IF IJ VB */
21
/*OT*/	{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0 },		/* OTHER */
22
/*OL*/	{ 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 0 },		/* OLET */
23
/*IL*/	{ 1, 1, 0, 1, 1, 1, 1, 3, 2, 1, 0 },		/* ILET */
24
/*DG*/	{ 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 0 },		/* DIG */
25
/*LP*/	{ 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 0 },		/* LPAR */
26
/*RP*/	{ 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 0 },		/* RPAR */
27
/*SL*/	{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0 },		/* SLASH */
28
/*PL*/	{ 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 0 },		/* PLUS */
29
/*IF*/	{ 3, 3, 1, 2, 2, 3, 2, 3, 0, 1, 1 },		/* ILETF */
30
/*IJ*/	{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0 },		/* ILETJ */
31
/*VB*/	{ 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 1 },		/* VBAR */
32
 
33
};
34
 
35
extern void shim(int, int);
36
extern void roman(int);
37
extern void sadd(char *);
38
extern void cadd(int);
39
extern int trans(int, char *);
40
 
41
int textc(void)	/* read next UTF rune from psp */
42
{
43
	wchar_t r;
44
	int w;
45
 
46
	w = mbtowc(&r, psp, UTFmax);
47
	if(w == 0){
48
		psp++;
49
		return 0;
50
	}
51
	if(w < 0){
52
		psp += 1;
53
		return Runeerror;	/* Plan 9-ism */
54
	}
55
	psp += w;
56
	return r;
57
}
58
 
59
void text(int t, char *p1)	/* convert text string p1 of type t */
60
{
61
	int c;
62
	char *p;
63
	tbl *tp;
64
 
65
	yyval = salloc();
66
	ebase[yyval] = 0;
67
	eht[yyval] = EM(1.0, ps);	/* ht in ems of orig size */
68
	lfont[yyval] = rfont[yyval] = ROM;
69
	lclass[yyval] = rclass[yyval] = OTHER;
70
	if (t == QTEXT) {
71
		for (p = p1; *p; p++)	/* scan for embedded \f's */
72
			if (*p == '\\' && *(p+1) == 'f')
73
				break;
74
		if (*p)		/* if found \f, leave it alone and hope */
75
			p = p1;
76
		else {
77
			sprintf(cs, "\\f%s%s\\fP", ftp->name, p1);
78
			p = cs;
79
		}
80
	} else if (t == SPACE)
81
		p = "\\ ";
82
	else if (t == THIN)
83
		p = "\\|";
84
	else if (t == TAB)
85
		p = "\\t";
86
	else if ((tp = lookup(restbl, p1)) != NULL) {
87
		p = tp->cval;
88
	} else {
89
		lf = rf = 0;
90
		lastft = 0;
91
		nclass = NONE;	/* get started with no class == no pad */
92
		csp = cs;
93
		for (psp = p1; (c = textc()) != '\0'; ) {
94
			nextft = ft;
95
			pclass = nclass;
96
			rf = trans(c, p1);
97
			if (lf == 0) {
98
				lf = rf;	/* left stuff is first found */
99
				lclass[yyval] = nclass;
100
			}
101
			if (csp-cs > CSSIZE)
102
				ERROR "converted token %.25s... too long", p1 FATAL ;
103
		}
104
		sadd("\\fP");
105
		*csp = '\0';
106
		p = cs;
107
		lfont[yyval] = lf;
108
		rfont[yyval] = rf;
109
		rclass[yyval] = nclass;
110
	}
111
	dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n",
112
		t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval], ps);
113
	printf(".ds %d \"%s\n", yyval, p);
114
}
115
 
116
int isdigitrune(int c)
117
{
118
	return ('0'<=c && c<='9');
119
}
120
 
121
int
122
trans(int c, char *)
123
{
124
	int f;
125
 
126
	if (isalpharune(c) && ft == ITAL && c != 'f' && c != 'j') {	/* italic letter */
127
		shim(pclass, nclass = ILET);
128
		cadd(c);
129
		return ITAL;
130
	}
131
	if (isalpharune(c) && ft != ITAL) {		/* other letter */
132
		shim(pclass, nclass = OLET);
133
		cadd(c);
134
		return ROM;
135
	}
136
	if (isdigitrune(c)) {
137
		shim(pclass, nclass = DIG);
138
		roman(c);
139
		return ROM;	/* this is the right side font of this object */
140
	}
141
	f = ROM;
142
	nclass = OTHER;
143
	switch (c) {
144
	case ':': case ';': case '!': case '%': case '?':
145
		shim(pclass, nclass);
146
		roman(c);
147
		return f;
148
	case '(': case '[':
149
		shim(pclass, nclass = LPAR);
150
		roman(c);
151
		return f;
152
	case ')': case ']':
153
		shim(pclass, nclass = RPAR);
154
		roman(c);
155
		return f;
156
	case ',':
157
		shim(pclass, nclass = OTHER);
158
		roman(c);
159
		return f;
160
	case '.':
161
		if (rf == ROM)
162
			roman(c);
163
		else
164
			cadd(c);
165
		return f;
166
	case '|':		/* postscript needs help with default width! */
167
		shim(pclass, nclass = VBAR);
168
		sadd("\\v'.17m'\\z|\\v'-.17m'\\|");	/* and height */
169
		return f;
170
	case '=':
171
		shim(pclass, nclass = PLUS);
172
		sadd("\\(eq");
173
		return f;
174
	case '+':
175
		shim(pclass, nclass = PLUS);
176
		sadd("\\(pl");
177
		return f;
178
	case '>':
179
	case '<':		/* >, >=, >>, <, <-, <=, << */
180
		shim(pclass, nclass = PLUS);
181
		if (*psp == '=') {
182
			sadd(c == '<' ? "\\(<=" : "\\(>=");
183
			psp++;
184
		} else if (c == '<' && *psp == '-') {	/* <- only */
185
			sadd("\\(<-");
186
			psp++;
187
		} else if (*psp == c) {		/* << or >> */
188
			cadd(c);
189
			cadd(c);
190
			psp++;
191
		} else {
192
			cadd(c);  
193
		}
194
		return f;
195
	case '-':
196
		shim(pclass, nclass = PLUS);	/* probably too big for ->'s */
197
		if (*psp == '>') {
198
			sadd("\\(->");
199
			psp++;
200
		} else {
201
			sadd("\\(mi");
202
		}
203
		return f;
204
	case '/':
205
		shim(pclass, nclass = SLASH);
206
		cadd('/');
207
		return f;
208
	case '~':
209
	case ' ':
210
		sadd("\\|\\|");
211
		return f;
212
	case '^':
213
		sadd("\\|");
214
		return f;
215
	case '\\':	/* troff - pass only \(xx without comment */
216
		shim(pclass, nclass);
217
		cadd('\\');
218
		cadd(c = *psp++);
219
		if (c == '(' && *psp && *(psp+1)) {
220
			cadd(*psp++);
221
			cadd(*psp++);
222
		} else
223
			fprintf(stderr, "eqn warning: unquoted troff command \\%c, file %s:%d\n",
224
				c, curfile->fname, curfile->lineno);
225
		return f;
226
	case '\'':
227
		shim(pclass, nclass);
228
		sadd("\\(fm");
229
		return f;
230
 
231
	case 'f':
232
		if (ft == ITAL) {
233
			shim(pclass, nclass = ILETF);
234
			cadd('f');
235
			f = ITAL;
236
		} else
237
			cadd('f');
238
		return f;
239
	case 'j':
240
		if (ft == ITAL) {
241
			shim(pclass, nclass = ILETJ);
242
			cadd('j');
243
			f = ITAL;
244
		} else
245
			cadd('j');
246
		return f;
247
	default:
248
		shim(pclass, nclass);
249
		cadd(c);
250
		return ft==ITAL ? ITAL : ROM;
251
	}
252
}
253
 
254
char *pad(int n)	/* return the padding as a string */
255
{
256
	static char buf[20];
257
 
258
	buf[0] = 0;
259
	if (n < 0) {
260
		sprintf(buf, "\\h'-%du*\\w'\\^'u'", -n);
261
		return buf;
262
	}	
263
	for ( ; n > 1; n -= 2)
264
		strcat(buf, "\\|");
265
	if (n > 0)
266
		strcat(buf, "\\^");
267
	return buf;
268
}
269
 
270
void shim(int lc, int rc)	/* add padding space suitable to left and right classes */
271
{
272
	sadd(pad(class[lc][rc]));
273
}
274
 
275
void roman(int c)	/* add char c in "roman" font */
276
{
277
	nextft = ROM;
278
	cadd(c);
279
}
280
 
281
void sadd(char *s)		/* add string s to cs */
282
{
283
	while (*s)
284
		cadd(*s++);
285
}
286
 
287
void cadd(int c)		/* add character c to end of cs */
288
{
289
	char *p;
290
	int w;
291
 
292
	if (lastft != nextft) {
293
		if (lastft != 0) {
294
			*csp++ = '\\';
295
			*csp++ = 'f';
296
			*csp++ = 'P';
297
		}
298
		*csp++ = '\\';
299
		*csp++ = 'f';
300
		if (ftp == ftstack) {	/* bottom level */
301
			if (ftp->ft == ITAL)	/* usual case */
302
				*csp++ = nextft;
303
			else		/* gfont set, use it */
304
				for (p = ftp->name; *csp = *p++; )
305
					csp++;
306
		} else {	/* inside some kind of font ... */
307
			for (p = ftp->name; *csp = *p++; )
308
				csp++;
309
		}
310
		lastft = nextft;
311
	}
312
	w = wctomb(csp, c);
313
	if(w > 0)	/* ignore bad characters */
314
		csp += w;
315
}