6 char cs
[CSSIZE
+20]; /* text string converted into this */
7 char *csp
; /* next spot in cs[] */
8 char *psp
; /* next character in input token */
10 int lf
, rf
; /* temporary spots for left and right fonts */
11 int lastft
; /* last \f added */
12 int nextft
; /* next \f to be added */
14 int pclass
; /* class of previous character */
15 int nclass
; /* class of next character */
17 int class[LAST
][LAST
] ={ /* guesswork, tuned to times roman postscript */
19 /*OT OL IL DG LP RP SL PL IF IJ VB */
20 /*OT*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OTHER */
21 /*OL*/ { 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OLET */
22 /*IL*/ { 1, 1, 0, 1, 1, 1, 1, 3, 2, 1, 0 }, /* ILET */
23 /*DG*/ { 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 0 }, /* DIG */
24 /*LP*/ { 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 0 }, /* LPAR */
25 /*RP*/ { 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 0 }, /* RPAR */
26 /*SL*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0 }, /* SLASH */
27 /*PL*/ { 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 0 }, /* PLUS */
28 /*IF*/ { 3, 3, 1, 2, 2, 3, 2, 3, 0, 1, 1 }, /* ILETF */
29 /*IJ*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0 }, /* ILETJ */
30 /*VB*/ { 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 1 }, /* VBAR */
34 extern void shim(int, int);
35 extern void roman(int);
36 extern void sadd(char *);
37 extern void cadd(int);
38 extern int trans(int, char *);
40 static int readutf8(int *dst
, char *src
)
50 while (l
< 6 && *s
& (0x40 >> l
))
52 *dst
= (0x3f >> l
) & *s
++;
54 *dst
= (*dst
<< 6) | (*s
++ & 0x3f);
58 static int writeutf8(char *dst
, int c
)
63 *d
++ = 0xf0 | (c
>> 18);
65 } else if (c
> 0x7ff) {
66 *d
++ = 0xe0 | (c
>> 12);
68 } else if (c
> 0x7f) {
69 *d
++ = 0xc0 | (c
>> 6);
72 *d
++ = c
> 0 ? c
: ' ';
76 *d
++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
80 int textc(void) /* read next UTF rune from psp */
85 w
= readutf8(&r
, psp
);
92 return 0x80; /* Plan 9-ism */
98 void text(int t
, char *p1
) /* convert text string p1 of type t */
106 eht
[yyval
] = EM(1.0, ps
); /* ht in ems of orig size */
107 lfont
[yyval
] = rfont
[yyval
] = ROM
;
108 lclass
[yyval
] = rclass
[yyval
] = OTHER
;
110 for (p
= p1
; *p
; p
++) /* scan for embedded \f's */
111 if (*p
== '\\' && *(p
+1) == 'f')
113 if (*p
) /* if found \f, leave it alone and hope */
116 sprintf(cs
, "\\f%s%s\\fP", ftp
->name
, p1
);
119 } else if (t
== SPACE
)
125 else if ((tp
= lookup(restbl
, p1
)) != NULL
) {
130 nclass
= NONE
; /* get started with no class == no pad */
132 for (psp
= p1
; (c
= textc()) != '\0'; ) {
137 lf
= rf
; /* left stuff is first found */
138 lclass
[yyval
] = nclass
;
141 ERROR
"converted token %.25s... too long", p1 FATAL
;
148 rclass
[yyval
] = nclass
;
150 dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n",
151 t
, yyval
, p
, ebase
[yyval
], eht
[yyval
], lfont
[yyval
], rfont
[yyval
], ps
);
152 printf(".ds %d \"%s\n", yyval
, p
);
155 int isalpharune(int c
)
157 return ('a'<=c
&& c
<='z') || ('A'<=c
&& c
<='Z');
160 int isdigitrune(int c
)
162 return ('0'<=c
&& c
<='9');
165 trans(int c
, char *p1
)
169 if (isalpharune(c
) && ft
== ITAL
&& c
!= 'f' && c
!= 'j') { /* italic letter */
170 shim(pclass
, nclass
= ILET
);
174 if (isalpharune(c
) && ft
!= ITAL
) { /* other letter */
175 shim(pclass
, nclass
= OLET
);
179 if (isdigitrune(c
)) {
180 shim(pclass
, nclass
= DIG
);
182 return ROM
; /* this is the right side font of this object */
187 case ':': case ';': case '!': case '%': case '?':
188 shim(pclass
, nclass
);
192 shim(pclass
, nclass
= LPAR
);
196 shim(pclass
, nclass
= RPAR
);
200 shim(pclass
, nclass
= OTHER
);
209 case '|': /* postscript needs help with default width! */
210 shim(pclass
, nclass
= VBAR
);
211 sadd("\\v'.17m'\\z|\\v'-.17m'\\|"); /* and height */
214 shim(pclass
, nclass
= PLUS
);
218 shim(pclass
, nclass
= PLUS
);
222 case '<': /* >, >=, >>, <, <-, <=, << */
223 shim(pclass
, nclass
= PLUS
);
225 sadd(c
== '<' ? "\\(<=" : "\\(>=");
227 } else if (c
== '<' && *psp
== '-') { /* <- only */
230 } else if (*psp
== c
) { /* << or >> */
239 shim(pclass
, nclass
= PLUS
); /* probably too big for ->'s */
248 shim(pclass
, nclass
= SLASH
);
258 case '\\': /* troff - pass only \(xx without comment */
259 shim(pclass
, nclass
);
262 if (c
== '(' && *psp
&& *(psp
+1)) {
266 fprintf(stderr
, "eqn warning: unquoted troff command \\%c, file %s:%d\n",
267 c
, curfile
->fname
, curfile
->lineno
);
270 shim(pclass
, nclass
);
276 shim(pclass
, nclass
= ILETF
);
284 shim(pclass
, nclass
= ILETJ
);
291 shim(pclass
, nclass
);
293 return ft
==ITAL
? ITAL
: ROM
;
297 char *pad(int n
) /* return the padding as a string */
303 sprintf(buf
, "\\h'-%du*\\w'\\^'u'", -n
);
306 for ( ; n
> 1; n
-= 2)
313 void shim(int lc
, int rc
) /* add padding space suitable to left and right classes */
315 sadd(pad(class[lc
][rc
]));
318 void roman(int c
) /* add char c in "roman" font */
324 void sadd(char *s
) /* add string s to cs */
330 void cadd(int c
) /* add character c to end of cs */
335 if (lastft
!= nextft
) {
343 if (ftp
== ftstack
) { /* bottom level */
344 if (ftp
->ft
== ITAL
) /* usual case */
346 else /* gfont set, use it */
347 for (p
= ftp
->name
; *csp
= *p
++; )
349 } else { /* inside some kind of font ... */
350 for (p
= ftp
->name
; *csp
= *p
++; )
355 w
= writeutf8(csp
, c
);
356 if(w
> 0) /* ignore bad characters */