Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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