xref: /plan9/sys/src/cmd/htmlroff/char.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
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