Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include "a.h"

/*
 * Translate Unicode to HTML by asking tcs(1).
 * This way we don't have yet another table.
 */
Rune*
rune2html(Rune r)
{
        static Biobuf b;
        static int fd = -1;
        static Rune **tcscache[256];
        int p[2];
        char *q;
        
        if(r == '\n')
                return L("\n");

        if(((uint)r&~0xFFFF) != 0){
                /* The cache must grow a lot to handle them */
                fprint(2, "%s: can't handle rune '%C'\n", argv0, r);
                return L("?");
        }

        if(tcscache[r>>8] && tcscache[r>>8][r&0xFF])
                return tcscache[r>>8][r&0xFF];

        if(fd < 0){
                if(pipe(p) < 0)
                        sysfatal("pipe: %r");
                switch(fork()){
                case -1:
                        sysfatal("fork: %r");
                case 0:
                        dup(p[0], 0);
                        dup(p[1], 1);
                        close(p[0]);
                        close(p[1]);
                        execl("/bin/tcs", "tcs", "-t", "html", nil);
                        _exits(0);
                default:
                        fd = p[1];
                        Binit(&b, p[0], OREAD);
                        break;
                }
        }
        /* HACK: extra newlines force rune+\n through tcs now */
        fprint(fd, "%C\n\n\n\n", r);
        q = Brdline(&b, '\n');
        while (q != nil && *q == '\n')
                q = Brdline(&b, '\n');
        if(q == nil)
                sysfatal("tcs: early eof");
        q[Blinelen(&b)-1] = 0;
        if(tcscache[r>>8] == nil)
                tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]);
        tcscache[r>>8][r&0xFF] = erunesmprint("%s", q);
        return tcscache[r>>8][r&0xFF];
}

/*
 * Translate troff to Unicode by looking in troff's utfmap.
 * This way we don't have yet another hard-coded table.
 */
typedef struct Trtab Trtab;
struct Trtab
{
        char t[UTFmax];
        Rune r;
};

static Trtab trtab[200];
int ntrtab;

static Trtab trinit[] =
{
        "pl",           Upl,
        "eq",   Ueq,
        "em",   0x2014,
        "en",   0x2013,
        "mi",   Umi,
        "fm",   0x2032,
};

Rune
troff2rune(Rune *rs)
{
        char *file, *f[10], *p, s[3];
        int i, nf;
        Biobuf *b;
        
        if(rs[0] >= Runeself || rs[1] >= Runeself)
                return Runeerror;
        s[0] = rs[0];
        s[1] = rs[1];
        s[2] = 0;
        if(ntrtab == 0){
                for(i=0; i<nelem(trinit) && ntrtab < nelem(trtab); i++){
                        trtab[ntrtab] = trinit[i];
                        ntrtab++;
                }
                file = "/sys/lib/troff/font/devutf/utfmap";
                if((b = Bopen(file, OREAD)) == nil)
                        sysfatal("open %s: %r", file);
                while((p = Brdline(b, '\n')) != nil){
                        p[Blinelen(b)-1] = 0;
                        nf = getfields(p, f, nelem(f), 0, "\t");
                        for(i=0; i+2<=nf && ntrtab<nelem(trtab); i+=2){
                                chartorune(&trtab[ntrtab].r, f[i]);
                                memmove(trtab[ntrtab].t, f[i+1], 2);
                                ntrtab++;
                        }
                }
                Bterm(b);
                
                if(ntrtab >= nelem(trtab))
                        fprint(2, "%s: trtab too small\n", argv0);
        }
        
        for(i=0; i<ntrtab; i++)
                if(strcmp(s, trtab[i].t) == 0)
                        return trtab[i].r;
        return Runeerror;
}