xref: /plan9/sys/src/cmd/htmlroff/char.c (revision f9e1cf08d3be51592e03e639fc848a68dc31a55e)
1 #include "a.h"
2 
3 /*
4  * Translate Unicode to HTML by asking tcs(1).
5  * This way we don't have yet another table.
6  */
7 Rune*
8 rune2html(Rune r)
9 {
10 	static Biobuf b;
11 	static int fd = -1;
12 	static Rune **tcscache[256];
13 	int p[2];
14 	char *q;
15 
16 	if(r == '\n')
17 		return L("\n");
18 
19 	if(tcscache[r>>8] && tcscache[r>>8][r&0xFF])
20 		return tcscache[r>>8][r&0xFF];
21 
22 	if(fd < 0){
23 		if(pipe(p) < 0)
24 			sysfatal("pipe: %r");
25 		switch(fork()){
26 		case -1:
27 			sysfatal("fork: %r");
28 		case 0:
29 			dup(p[0], 0);
30 			dup(p[1], 1);
31 			close(p[0]);
32 			close(p[1]);
33 			execl("/bin/tcs", "tcs", "-t", "html", nil);
34 			_exits(0);
35 		default:
36 			fd = p[1];
37 			Binit(&b, p[0], OREAD);
38 			break;
39 		}
40 	}
41 	/* HACK: extra newlines force rune+\n through tcs now */
42 	fprint(fd, "%C\n\n\n\n", r);
43 	q = Brdline(&b, '\n');
44 	while (q != nil && *q == '\n')
45 		q = Brdline(&b, '\n');
46 	if(q == nil)
47 		sysfatal("tcs: early eof");
48 	q[Blinelen(&b)-1] = 0;
49 	if(tcscache[r>>8] == nil)
50 		tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]);
51 	tcscache[r>>8][r&0xFF] = erunesmprint("%s", q);
52 	return tcscache[r>>8][r&0xFF];
53 }
54 
55 /*
56  * Translate troff to Unicode by looking in troff's utfmap.
57  * This way we don't have yet another hard-coded table.
58  */
59 typedef struct Trtab Trtab;
60 struct Trtab
61 {
62 	char t[3];
63 	Rune r;
64 };
65 
66 static Trtab trtab[200];
67 int ntrtab;
68 
69 static Trtab trinit[] =
70 {
71 	"pl",		Upl,
72 	"eq",	Ueq,
73 	"em",	0x2014,
74 	"en",	0x2013,
75 	"mi",	Umi,
76 	"fm",	0x2032,
77 };
78 
79 Rune
80 troff2rune(Rune *rs)
81 {
82 	char *file, *f[10], *p, s[3];
83 	int i, nf;
84 	Biobuf *b;
85 
86 	if(rs[0] >= Runeself || rs[1] >= Runeself)
87 		return Runeerror;
88 	s[0] = rs[0];
89 	s[1] = rs[1];
90 	s[2] = 0;
91 	if(ntrtab == 0){
92 		for(i=0; i<nelem(trinit) && ntrtab < nelem(trtab); i++){
93 			trtab[ntrtab] = trinit[i];
94 			ntrtab++;
95 		}
96 		file = "/sys/lib/troff/font/devutf/utfmap";
97 		if((b = Bopen(file, OREAD)) == nil)
98 			sysfatal("open %s: %r", file);
99 		while((p = Brdline(b, '\n')) != nil){
100 			p[Blinelen(b)-1] = 0;
101 			nf = getfields(p, f, nelem(f), 0, "\t");
102 			for(i=0; i+2<=nf && ntrtab<nelem(trtab); i+=2){
103 				chartorune(&trtab[ntrtab].r, f[i]);
104 				memmove(trtab[ntrtab].t, f[i+1], 2);
105 				ntrtab++;
106 			}
107 		}
108 		Bterm(b);
109 
110 		if(ntrtab >= nelem(trtab))
111 			fprint(2, "%s: trtab too small\n", argv0);
112 	}
113 
114 	for(i=0; i<ntrtab; i++)
115 		if(strcmp(s, trtab[i].t) == 0)
116 			return trtab[i].r;
117 	return Runeerror;
118 }
119 
120