262 lines
7 KiB
C
262 lines
7 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
#include "../common/common.h"
|
|
#include "tr2post.h"
|
|
|
|
int hpos = 0, vpos = 0;
|
|
int fontsize, fontpos;
|
|
|
|
#define MAXSTR 128
|
|
int trindex; /* index into trofftab of current troff font */
|
|
static int expecthmot = 0;
|
|
|
|
void
|
|
initialize(void) {
|
|
}
|
|
|
|
void
|
|
hgoto(int x) {
|
|
hpos = x;
|
|
if (pageon()) {
|
|
endstring();
|
|
/* Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
|
|
}
|
|
}
|
|
|
|
void
|
|
vgoto(int y) {
|
|
vpos = y;
|
|
if (pageon()) {
|
|
endstring();
|
|
/* Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
|
|
}
|
|
}
|
|
|
|
void
|
|
hmot(int x) {
|
|
int delta;
|
|
|
|
if ((x<expecthmot-1) || (x>expecthmot+1)) {
|
|
delta = x - expecthmot;
|
|
if (curtrofffontid <0 || curtrofffontid >= troffontcnt) {
|
|
Bprint(Bstderr, "troffontcnt=%d curtrofffontid=%d\n", troffontcnt, curtrofffontid);
|
|
Bflush(Bstderr);
|
|
exits("");
|
|
}
|
|
if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10 && isinstring()) {
|
|
if (pageon()) runeout(' ');
|
|
} else {
|
|
if (pageon()) {
|
|
endstring();
|
|
/* Bprint(Bstdout, " %d 0 rmoveto ", delta); */
|
|
/* Bprint(Bstdout, " %d %d m ", hpos+x, vpos); */
|
|
if (debug) Bprint(Bstderr, "x=%d expecthmot=%d\n", x, expecthmot);
|
|
}
|
|
}
|
|
}
|
|
hpos += x;
|
|
expecthmot = 0;
|
|
}
|
|
|
|
void
|
|
vmot(int y) {
|
|
endstring();
|
|
/* Bprint(Bstdout, " 0 %d rmoveto ", -y); */
|
|
vpos += y;
|
|
}
|
|
|
|
struct charent **
|
|
findglyph(int trfid, Rune rune, char *stoken) {
|
|
struct charent **cp;
|
|
|
|
for (cp = &(troffontab[trfid].charent[RUNEGETGROUP(rune)][RUNEGETCHAR(rune)]); *cp != 0; cp = &((*cp)->next)) {
|
|
if ((*cp)->name) {
|
|
if (debug) Bprint(Bstderr, "looking for <%s>, have <%s> in font %s\n", stoken, (*cp)->name, troffontab[trfid].trfontid);
|
|
if (strcmp((*cp)->name, stoken) == 0)
|
|
break;
|
|
}
|
|
}
|
|
return(cp);
|
|
}
|
|
|
|
/* output glyph. Use first rune to look up character (hash)
|
|
* then use stoken UTF string to find correct glyph in linked
|
|
* list of glyphs in bucket.
|
|
*/
|
|
void
|
|
glyphout(Rune rune, char *stoken, BOOLEAN specialflag) {
|
|
struct charent **cp;
|
|
struct troffont *tfp;
|
|
struct psfent *psfp = (struct psfent*)0;
|
|
int i, t;
|
|
int fontid; /* this is the troff font table index, not the mounted font table index */
|
|
int mi, wid;
|
|
Rune r;
|
|
|
|
mi = 0;
|
|
settrfont();
|
|
|
|
/* check current font for the character, special or not */
|
|
fontid = curtrofffontid;
|
|
if (debug) fprint(2, " looking through current font: trying %s\n", troffontab[fontid].trfontid);
|
|
cp = findglyph(fontid, rune, stoken);
|
|
if (*cp != 0) goto foundit;
|
|
|
|
if (specialflag) {
|
|
if (expecthmot) hmot(0);
|
|
|
|
/* check special fonts for the special character */
|
|
/* cycle through the (troff) mounted fonts starting at the next font */
|
|
for (mi=0; mi<fontmnt; mi++) {
|
|
if (troffontab[fontid].trfontid==0) error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",
|
|
fontid, troffontab[fontid].trfontid);
|
|
if (fontmtab[mi]==0) {
|
|
if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", mi, fontmtab[mi], fontmnt);
|
|
continue;
|
|
}
|
|
if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0) break;
|
|
}
|
|
if (mi==fontmnt) error(FATAL, "current troff font is not mounted, botch!\n");
|
|
for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
|
|
if (fontmtab[i]==0) {
|
|
if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", i, fontmtab[i], fontmnt);
|
|
continue;
|
|
}
|
|
fontid = findtfn(fontmtab[i], TRUE);
|
|
if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
|
|
if (troffontab[fontid].special) {
|
|
cp = findglyph(fontid, rune, stoken);
|
|
if (*cp != 0) goto foundit;
|
|
}
|
|
}
|
|
|
|
/* check font 1 (if current font is not font 1) for the special character */
|
|
if (mi != 1) {
|
|
fontid = findtfn(fontmtab[1], TRUE);;
|
|
if (debug) fprint(2, " looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);
|
|
cp = findglyph(fontid, rune, stoken);
|
|
if (*cp != 0) goto foundit;
|
|
}
|
|
}
|
|
|
|
if (*cp == 0) {
|
|
error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
|
|
troffontab[curtrofffontid].trfontid);
|
|
expecthmot = 0;
|
|
}
|
|
|
|
/* use the peter face in lieu of the character that we couldn't find */
|
|
rune = 'p'; stoken = "pw";
|
|
for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
|
|
if (fontmtab[i]==0) {
|
|
if (debug) fprint(2, "fontmtab[%d]=0x%x\n", i, fontmtab[i]);
|
|
continue;
|
|
}
|
|
fontid = findtfn(fontmtab[i], TRUE);
|
|
if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
|
|
if (troffontab[fontid].special) {
|
|
cp = findglyph(fontid, rune, stoken);
|
|
if (*cp != 0) goto foundit;
|
|
}
|
|
}
|
|
|
|
if (*cp == 0) {
|
|
error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
|
|
troffontab[curtrofffontid].trfontid);
|
|
expecthmot = 0;
|
|
return;
|
|
}
|
|
|
|
foundit:
|
|
t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff);
|
|
if (debug) {
|
|
Bprint(Bstderr, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n",
|
|
rune, rune, (*cp)->postfontid, (*cp)->postcharid, (*cp)->troffcharwidth);
|
|
}
|
|
|
|
tfp = &(troffontab[fontid]);
|
|
for (i=0; i<tfp->psfmapsize; i++) {
|
|
psfp = &(tfp->psfmap[i]);
|
|
if(t>=psfp->start && t<=psfp->end) break;
|
|
}
|
|
if (i >= tfp->psfmapsize)
|
|
error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune);
|
|
|
|
setpsfont(psfp->psftid, fontsize);
|
|
|
|
if (t == 0x0001) { /* character is in charlib */
|
|
endstring();
|
|
if (pageon()) {
|
|
Bprint(Bstdout, "%d %d m ", hpos, vpos);
|
|
/* if char is unicode character rather than name, clean up for postscript */
|
|
wid = chartorune(&r, (*cp)->name);
|
|
if(' '<r && r<0x7F)
|
|
Bprint(Bstdout, "%d build_%s\n", (*cp)->troffcharwidth, (*cp)->name);
|
|
else{
|
|
if((*cp)->name[wid] != 0)
|
|
error(FATAL, "character <%s> badly named\n", (*cp)->name);
|
|
Bprint(Bstdout, "%d build_X%.4x\n", (*cp)->troffcharwidth, r);
|
|
}
|
|
|
|
/* stash charent pointer in a list so that we can print these character definitions
|
|
* in the prologue.
|
|
*/
|
|
for (i=0; i<build_char_cnt; i++)
|
|
if (*cp == build_char_list[i]) break;
|
|
if (i == build_char_cnt) {
|
|
build_char_list = galloc(build_char_list, sizeof(struct charent *) * ++build_char_cnt,
|
|
"build_char_list");
|
|
build_char_list[build_char_cnt-1] = *cp;
|
|
}
|
|
}
|
|
expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
|
|
} else if (isinstring() || rune != ' ') {
|
|
startstring();
|
|
if (pageon()) {
|
|
if (rune == ' ')
|
|
Bprint(Bstdout, " ");
|
|
else
|
|
Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str);
|
|
}
|
|
expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
|
|
}
|
|
}
|
|
|
|
/* runeout puts a symbol into a string (queue) to be output.
|
|
* It also has to keep track of the current and last symbol
|
|
* output to check that the spacing is correct by default
|
|
* or needs to be adjusted with a spacing operation.
|
|
*/
|
|
|
|
void
|
|
runeout(Rune rune) {
|
|
char stoken[UTFmax+1];
|
|
int i;
|
|
|
|
i = runetochar(stoken, &rune);
|
|
stoken[i] = '\0';
|
|
glyphout(rune, stoken, TRUE);
|
|
}
|
|
|
|
void
|
|
specialout(char *stoken) {
|
|
Rune rune;
|
|
|
|
chartorune(&rune, stoken);
|
|
glyphout(rune, stoken, TRUE);
|
|
}
|
|
|
|
void
|
|
graphfunc(Biobuf *bp) {
|
|
}
|
|
|
|
long
|
|
nametorune(char *name) {
|
|
return(0);
|
|
}
|
|
|
|
void
|
|
notavail(char *msg) {
|
|
Bprint(Bstderr, "%s is not available at this time.\n", msg);
|
|
}
|