1426d2b71SDavid du Colombier #include "a.h"
2426d2b71SDavid du Colombier
3426d2b71SDavid du Colombier /*
4426d2b71SDavid du Colombier * Translate Unicode to HTML by asking tcs(1).
5426d2b71SDavid du Colombier * This way we don't have yet another table.
6426d2b71SDavid du Colombier */
7426d2b71SDavid du Colombier Rune*
rune2html(Rune r)8426d2b71SDavid du Colombier rune2html(Rune r)
9426d2b71SDavid du Colombier {
10426d2b71SDavid du Colombier static Biobuf b;
11426d2b71SDavid du Colombier static int fd = -1;
12426d2b71SDavid du Colombier static Rune **tcscache[256];
13426d2b71SDavid du Colombier int p[2];
14426d2b71SDavid du Colombier char *q;
15426d2b71SDavid du Colombier
16426d2b71SDavid du Colombier if(r == '\n')
17426d2b71SDavid du Colombier return L("\n");
18426d2b71SDavid du Colombier
19*82726826SDavid du Colombier if(((uint)r&~0xFFFF) != 0){
20*82726826SDavid du Colombier /* The cache must grow a lot to handle them */
21*82726826SDavid du Colombier fprint(2, "%s: can't handle rune '%C'\n", argv0, r);
22*82726826SDavid du Colombier return L("?");
23*82726826SDavid du Colombier }
24*82726826SDavid du Colombier
25426d2b71SDavid du Colombier if(tcscache[r>>8] && tcscache[r>>8][r&0xFF])
26426d2b71SDavid du Colombier return tcscache[r>>8][r&0xFF];
27426d2b71SDavid du Colombier
28426d2b71SDavid du Colombier if(fd < 0){
29426d2b71SDavid du Colombier if(pipe(p) < 0)
30426d2b71SDavid du Colombier sysfatal("pipe: %r");
31426d2b71SDavid du Colombier switch(fork()){
32426d2b71SDavid du Colombier case -1:
33426d2b71SDavid du Colombier sysfatal("fork: %r");
34426d2b71SDavid du Colombier case 0:
35426d2b71SDavid du Colombier dup(p[0], 0);
36c324cc80SDavid du Colombier dup(p[1], 1);
37c324cc80SDavid du Colombier close(p[0]);
38426d2b71SDavid du Colombier close(p[1]);
39426d2b71SDavid du Colombier execl("/bin/tcs", "tcs", "-t", "html", nil);
40426d2b71SDavid du Colombier _exits(0);
41426d2b71SDavid du Colombier default:
42426d2b71SDavid du Colombier fd = p[1];
43c324cc80SDavid du Colombier Binit(&b, p[0], OREAD);
44426d2b71SDavid du Colombier break;
45426d2b71SDavid du Colombier }
46426d2b71SDavid du Colombier }
47c324cc80SDavid du Colombier /* HACK: extra newlines force rune+\n through tcs now */
48c324cc80SDavid du Colombier fprint(fd, "%C\n\n\n\n", r);
49c324cc80SDavid du Colombier q = Brdline(&b, '\n');
50c324cc80SDavid du Colombier while (q != nil && *q == '\n')
51426d2b71SDavid du Colombier q = Brdline(&b, '\n');
52426d2b71SDavid du Colombier if(q == nil)
53426d2b71SDavid du Colombier sysfatal("tcs: early eof");
54426d2b71SDavid du Colombier q[Blinelen(&b)-1] = 0;
55426d2b71SDavid du Colombier if(tcscache[r>>8] == nil)
56426d2b71SDavid du Colombier tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]);
57426d2b71SDavid du Colombier tcscache[r>>8][r&0xFF] = erunesmprint("%s", q);
58426d2b71SDavid du Colombier return tcscache[r>>8][r&0xFF];
59426d2b71SDavid du Colombier }
60426d2b71SDavid du Colombier
61426d2b71SDavid du Colombier /*
62426d2b71SDavid du Colombier * Translate troff to Unicode by looking in troff's utfmap.
63426d2b71SDavid du Colombier * This way we don't have yet another hard-coded table.
64426d2b71SDavid du Colombier */
65426d2b71SDavid du Colombier typedef struct Trtab Trtab;
66426d2b71SDavid du Colombier struct Trtab
67426d2b71SDavid du Colombier {
68*82726826SDavid du Colombier char t[UTFmax];
69426d2b71SDavid du Colombier Rune r;
70426d2b71SDavid du Colombier };
71426d2b71SDavid du Colombier
72426d2b71SDavid du Colombier static Trtab trtab[200];
73426d2b71SDavid du Colombier int ntrtab;
74426d2b71SDavid du Colombier
75426d2b71SDavid du Colombier static Trtab trinit[] =
76426d2b71SDavid du Colombier {
77426d2b71SDavid du Colombier "pl", Upl,
78426d2b71SDavid du Colombier "eq", Ueq,
79426d2b71SDavid du Colombier "em", 0x2014,
80426d2b71SDavid du Colombier "en", 0x2013,
81426d2b71SDavid du Colombier "mi", Umi,
82426d2b71SDavid du Colombier "fm", 0x2032,
83426d2b71SDavid du Colombier };
84426d2b71SDavid du Colombier
85426d2b71SDavid du Colombier Rune
troff2rune(Rune * rs)86426d2b71SDavid du Colombier troff2rune(Rune *rs)
87426d2b71SDavid du Colombier {
88426d2b71SDavid du Colombier char *file, *f[10], *p, s[3];
89426d2b71SDavid du Colombier int i, nf;
90426d2b71SDavid du Colombier Biobuf *b;
91426d2b71SDavid du Colombier
92426d2b71SDavid du Colombier if(rs[0] >= Runeself || rs[1] >= Runeself)
93426d2b71SDavid du Colombier return Runeerror;
94426d2b71SDavid du Colombier s[0] = rs[0];
95426d2b71SDavid du Colombier s[1] = rs[1];
96426d2b71SDavid du Colombier s[2] = 0;
97426d2b71SDavid du Colombier if(ntrtab == 0){
98426d2b71SDavid du Colombier for(i=0; i<nelem(trinit) && ntrtab < nelem(trtab); i++){
99426d2b71SDavid du Colombier trtab[ntrtab] = trinit[i];
100426d2b71SDavid du Colombier ntrtab++;
101426d2b71SDavid du Colombier }
102426d2b71SDavid du Colombier file = "/sys/lib/troff/font/devutf/utfmap";
103426d2b71SDavid du Colombier if((b = Bopen(file, OREAD)) == nil)
104426d2b71SDavid du Colombier sysfatal("open %s: %r", file);
105426d2b71SDavid du Colombier while((p = Brdline(b, '\n')) != nil){
106426d2b71SDavid du Colombier p[Blinelen(b)-1] = 0;
107426d2b71SDavid du Colombier nf = getfields(p, f, nelem(f), 0, "\t");
108426d2b71SDavid du Colombier for(i=0; i+2<=nf && ntrtab<nelem(trtab); i+=2){
109426d2b71SDavid du Colombier chartorune(&trtab[ntrtab].r, f[i]);
110426d2b71SDavid du Colombier memmove(trtab[ntrtab].t, f[i+1], 2);
111426d2b71SDavid du Colombier ntrtab++;
112426d2b71SDavid du Colombier }
113426d2b71SDavid du Colombier }
114426d2b71SDavid du Colombier Bterm(b);
115426d2b71SDavid du Colombier
116426d2b71SDavid du Colombier if(ntrtab >= nelem(trtab))
117426d2b71SDavid du Colombier fprint(2, "%s: trtab too small\n", argv0);
118426d2b71SDavid du Colombier }
119426d2b71SDavid du Colombier
120426d2b71SDavid du Colombier for(i=0; i<ntrtab; i++)
121426d2b71SDavid du Colombier if(strcmp(s, trtab[i].t) == 0)
122426d2b71SDavid du Colombier return trtab[i].r;
123426d2b71SDavid du Colombier return Runeerror;
124426d2b71SDavid du Colombier }
125426d2b71SDavid du Colombier
126