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 CM */
20 /*OT*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0 }, /* OTHER */
21 /*OL*/ { 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0 }, /* OLET */
22 /*IL*/ { 1, 1, 0, 1, 1, 1, 1, 3, 2, 1, 0, 0 }, /* ILET */
23 /*DG*/ { 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 0, 0 }, /* DIG */
24 /*LP*/ { 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 0, 0 }, /* LPAR */
25 /*RP*/ { 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 0, 0 }, /* RPAR */
26 /*SL*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0 }, /* SLASH */
27 /*PL*/ { 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 0, 0 }, /* PLUS */
28 /*IF*/ { 3, 3, 1, 2, 2, 3, 2, 3, 0, 1, 1, 0 }, /* ILETF */
29 /*IJ*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0 }, /* ILETJ */
30 /*VB*/ { 1, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1 }, /* VBAR */
31 /*CM*/ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, /* COMMA */
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 *);
41 static int readutf8(int *dst
, char *src
)
51 while (l
< 6 && *s
& (0x40 >> l
))
53 *dst
= (0x3f >> l
) & *s
++;
55 *dst
= (*dst
<< 6) | (*s
++ & 0x3f);
59 static int writeutf8(char *dst
, int c
)
64 *d
++ = 0xf0 | (c
>> 18);
66 } else if (c
> 0x7ff) {
67 *d
++ = 0xe0 | (c
>> 12);
69 } else if (c
> 0x7f) {
70 *d
++ = 0xc0 | (c
>> 6);
73 *d
++ = c
> 0 ? c
: ' ';
77 *d
++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
81 int textc(void) /* read next UTF rune from psp */
86 w
= readutf8(&r
, psp
);
93 return 0x80; /* Plan 9-ism */
99 void text(int t
, char *p1
) /* convert text string p1 of type t */
107 eht
[yyval
] = EM(1.0, ps
); /* ht in ems of orig size */
108 lfont
[yyval
] = rfont
[yyval
] = ROM
;
109 lclass
[yyval
] = rclass
[yyval
] = OTHER
;
111 for (p
= p1
; *p
; p
++) /* scan for embedded \f's */
112 if (*p
== '\\' && *(p
+1) == 'f')
114 if (*p
) /* if found \f, leave it alone and hope */
117 sprintf(cs
, "\\f%s%s\\fP", ftp
->name
, p1
);
120 } else if (t
== SPACE
)
126 else if ((tp
= lookup(restbl
, p1
)) != NULL
) {
131 nclass
= NONE
; /* get started with no class == no pad */
133 for (psp
= p1
; (c
= textc()) != '\0'; ) {
138 lf
= rf
; /* left stuff is first found */
139 lclass
[yyval
] = nclass
;
142 ERROR
"converted token %.25s... too long", p1 FATAL
;
149 rclass
[yyval
] = nclass
;
151 dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n",
152 t
, yyval
, p
, ebase
[yyval
], eht
[yyval
], lfont
[yyval
], rfont
[yyval
], ps
);
153 printf(".ds %d \"%s\n", yyval
, p
);
156 int isalpharune(int c
)
158 return ('a'<=c
&& c
<='z') || ('A'<=c
&& c
<='Z');
161 int isdigitrune(int c
)
163 return ('0'<=c
&& c
<='9');
166 trans(int c
, char *p1
)
170 if (isalpharune(c
) && ft
== ITAL
&& c
!= 'f' && c
!= 'j') { /* italic letter */
171 shim(pclass
, nclass
= ILET
);
175 if (isalpharune(c
) && ft
!= ITAL
) { /* other letter */
176 shim(pclass
, nclass
= OLET
);
180 if (isdigitrune(c
)) {
181 shim(pclass
, nclass
= DIG
);
183 return ROM
; /* this is the right side font of this object */
188 case ':': case ';': case '!': case '%': case '?':
189 shim(pclass
, nclass
);
193 shim(pclass
, nclass
= LPAR
);
197 shim(pclass
, nclass
= RPAR
);
201 shim(pclass
, nclass
= COMMA
);
210 case '|': /* postscript needs help with default width! */
211 shim(pclass
, nclass
= VBAR
);
212 sadd("|"); /* and height */
215 shim(pclass
, nclass
= PLUS
);
219 shim(pclass
, nclass
= PLUS
);
223 case '<': /* >, >=, >>, <, <-, <=, << */
224 shim(pclass
, nclass
= PLUS
);
226 sadd(c
== '<' ? "\\(<=" : "\\(>=");
228 } else if (c
== '<' && *psp
== '-') { /* <- only */
231 } else if (*psp
== c
) { /* << or >> */
240 shim(pclass
, nclass
= PLUS
); /* probably too big for ->'s */
249 shim(pclass
, nclass
= SLASH
);
259 case '\\': /* troff - pass only \(xx without comment */
260 shim(pclass
, nclass
);
263 if (c
== '(' && *psp
&& *(psp
+1)) {
267 fprintf(stderr
, "eqn warning: unquoted troff command \\%c, file %s:%d\n",
268 c
, curfile
->fname
, curfile
->lineno
);
271 shim(pclass
, nclass
);
277 shim(pclass
, nclass
= ILETF
);
285 shim(pclass
, nclass
= ILETJ
);
292 shim(pclass
, nclass
);
294 return ft
==ITAL
? ITAL
: ROM
;
298 char *pad(int n
) /* return the padding as a string */
304 sprintf(buf
, "\\h'-%du*\\w'\\^'u'", -n
);
307 for ( ; n
> 1; n
-= 2)
314 void shim(int lc
, int rc
) /* add padding space suitable to left and right classes */
316 sadd(pad(class[lc
][rc
]));
319 void roman(int c
) /* add char c in "roman" font */
325 void sadd(char *s
) /* add string s to cs */
331 void cadd(int c
) /* add character c to end of cs */
336 if (lastft
!= nextft
) {
344 if (ftp
== ftstack
) { /* bottom level */
345 if (ftp
->ft
== ITAL
) /* usual case */
347 else /* gfont set, use it */
348 for (p
= ftp
->name
; *csp
= *p
++; )
350 } else { /* inside some kind of font ... */
351 for (p
= ftp
->name
; *csp
= *p
++; )
356 w
= writeutf8(csp
, c
);
357 if(w
> 0) /* ignore bad characters */