blob: b037bdda3d49d0c679a8f5d0ead5d6b8508903dc [file] [log] [blame]
#include "tdef.h"
#include "fns.h"
#include "ext.h"
/*
* troff10.c
*
* typesetter interface
*/
int vpos = 0; /* absolute vertical position on page */
int hpos = 0; /* ditto horizontal */
extern Font fonts[MAXFONTS+1];
int Inch;
int Hor;
int Vert;
int Unitwidth;
int nfonts;
void t_ptinit(void)
{
int i;
char buf[100], *p;
hmot = t_hmot;
makem = t_makem;
setabs = t_setabs;
setch = t_setch;
sethl = t_sethl;
setht = t_setht;
setslant = t_setslant;
vmot = t_vmot;
xlss = t_xlss;
findft = t_findft;
width = t_width;
mchbits = t_mchbits;
ptlead = t_ptlead;
ptout = t_ptout;
ptpause = t_ptpause;
setfont = t_setfont;
setps = t_setps;
setwd = t_setwd;
/* open table for device, */
/* read in resolution, size info, font info, etc., set params */
if ((p = getenv("TYPESETTER")) != 0)
strcpy(devname, p);
if (termtab[0] == 0)
strcpy(termtab, DWBfontdir);
if (fontdir[0] == 0)
strcpy(fontdir, DWBfontdir);
if (devname[0] == 0)
strcpy(devname, TDEVNAME);
hyf = 1;
lg = 1;
sprintf(buf, "/dev%s/DESC", devname);
strcat(termtab, buf);
if (getdesc(termtab) < 0) {
ERROR "can't open DESC file %s", termtab WARN;
done3(1);
}
if (!ascii) {
OUT "x T %s\n", devname PUT;
OUT "x res %d %d %d\n", Inch, Hor, Vert PUT;
OUT "x init\n" PUT;
}
for (i = 1; i <= nfonts; i++)
setfp(i, fontlab[i], (char *) 0, 0);
sps = EM/3; /* space size */
ics = EM; /* insertion character space */
for (i = 0; i < (NTAB - 1) && DTAB * (i + 1) < TABMASK; i++)
tabtab[i] = DTAB * (i + 1);
tabtab[NTAB-1] = 0;
pl = 11 * INCH; /* paper length */
po = PO; /* page offset */
spacesz = SS;
lss = lss1 = VS;
ll = ll1 = lt = lt1 = LL;
t_specnames(); /* install names like "hyphen", etc. */
}
void t_specnames(void)
{
int i;
for (i = 0; spnames[i].n; i++)
*spnames[i].n = chadd(spnames[i].v, Troffchar, Install);
}
void t_ptout(Tchar i)
{
int dv;
Tchar *k;
int temp, a, b;
int diff;
if (cbits(i) != '\n') {
if (olinep >= oline + olnsize) {
diff = olinep - oline;
olnsize += OLNSIZE;
if ((oline = (Tchar *)realloc((char *)oline, olnsize * sizeof(Tchar))) != NULL) {
if (diff && olinep)
olinep = oline + diff;
} else {
ERROR "Output line overflow." WARN;
done(2);
}
}
*olinep++ = i;
return;
}
if (olinep == oline) {
lead += lss;
return;
}
hpos = po; /* ??? */
esc = 0; /* ??? */
ptesc(); /* the problem is to get back to the left end of the line */
dv = 0;
for (k = oline; k < olinep; k++) {
if (ismot(*k) && isvmot(*k)) {
temp = absmot(*k);
if (isnmot(*k))
temp = -temp;
dv += temp;
}
}
if (dv) {
vflag++;
*olinep++ = makem(-dv);
vflag = 0;
}
b = dip->blss + lss;
lead += dip->blss + lss;
dip->blss = 0;
for (k = oline; k < olinep; )
k += ptout0(k); /* now passing a pointer! */
olinep = oline;
lead += dip->alss;
a = dip->alss;
dip->alss = 0;
/*
OUT "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos PUT;
*/
OUT "n%d %d\n", b, a PUT; /* be nice to chuck */
}
int ptout0(Tchar *pi)
{
int j, k, w;
int z, dx, dy, dx2, dy2, n;
Tchar i;
int outsize; /* size of object being printed */
w = 0;
outsize = 1; /* default */
i = *pi;
k = cbits(i);
if (ismot(i)) {
j = absmot(i);
if (isnmot(i))
j = -j;
if (isvmot(i))
lead += j;
else
esc += j;
return(outsize);
}
if (k == CHARHT) {
xpts = fbits(i); /* sneaky, font bits as size bits */
if (xpts != mpts)
ptps();
OUT "x H %ld\n", sbits(i) PUT;
return(outsize);
}
if (k == SLANT) {
OUT "x S %ld\n", sfbits(i)-180 PUT;
return(outsize);
}
if (k == WORDSP) {
oput('w');
return(outsize);
}
if (sfbits(i) == oldbits) {
xfont = pfont;
xpts = ppts;
} else
xbits(i, 2);
if (k == XON) {
extern int xon;
ptflush(); /* guarantee that everything is out */
if (esc)
ptesc();
if (xfont != mfont)
ptfont();
if (xpts != mpts)
ptps();
if (lead)
ptlead();
OUT "x X " PUT;
xon++;
for (j = 1; cbits(pi[j]) != XOFF; j++)
outascii(pi[j]);
oput('\n');
xon--;
return j+1;
}
if (k < 040 && k != DRAWFCN)
return(outsize);
j = z = 0;
if (k != DRAWFCN) {
if (widcache[k].fontpts == (xfont<<8) + xpts && !setwdf) {
w = widcache[k].width;
bd = 0;
cs = 0;
} else
w = getcw(k);
if (cs) {
if (bd)
w += (bd - 1) * HOR;
j = (cs - w) / 2;
w = cs - j;
if (bd)
w -= (bd - 1) * HOR;
}
if (iszbit(i)) {
if (cs)
w = -j;
else
w = 0;
z = 1;
}
}
esc += j;
if (xfont != mfont)
ptfont();
if (xpts != mpts)
ptps();
if (lead)
ptlead();
/* put out the real character here */
if (k == DRAWFCN) {
if (esc)
ptesc();
w = 0;
dx = absmot(pi[3]);
if (isnmot(pi[3]))
dx = -dx;
dy = absmot(pi[4]);
if (isnmot(pi[4]))
dy = -dy;
switch (cbits(pi[1])) {
case DRAWCIRCLE: /* circle */
OUT "D%c %d\n", DRAWCIRCLE, dx PUT; /* dx is diameter */
hpos += dx;
break;
case DRAWELLIPSE:
OUT "D%c %d %d\n", DRAWELLIPSE, dx, dy PUT;
hpos += dx;
break;
case DRAWBUILD:
k = cbits(pi[2]);
OUT "D%c %d ", DRAWBUILD, dx PUT;
if (k < ALPHABET)
OUT "%c\n", k PUT;
else
ptchname(k);
hpos += dx;
break;
case DRAWLINE: /* line */
k = cbits(pi[2]);
OUT "D%c %d %d ", DRAWLINE, dx, dy PUT;
if (k < ALPHABET)
OUT "%c\n", k PUT;
else
ptchname(k);
hpos += dx;
vpos += dy;
break;
case DRAWARC: /* arc */
dx2 = absmot(pi[5]);
if (isnmot(pi[5]))
dx2 = -dx2;
dy2 = absmot(pi[6]);
if (isnmot(pi[6]))
dy2 = -dy2;
OUT "D%c %d %d %d %d\n", DRAWARC,
dx, dy, dx2, dy2 PUT;
hpos += dx + dx2;
vpos += dy + dy2;
break;
case 's': /* using 's' internally to avoid .tr ~ */
pi[1] = '~';
case DRAWSPLINE: /* spline */
default: /* something else; copy it like spline */
OUT "D%c %d %d", (char)cbits(pi[1]), dx, dy PUT;
hpos += dx;
vpos += dy;
if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) {
/* it was somehow defective */
OUT "\n" PUT;
break;
}
for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) {
dx = absmot(pi[n]);
if (isnmot(pi[n]))
dx = -dx;
dy = absmot(pi[n+1]);
if (isnmot(pi[n+1]))
dy = -dy;
OUT " %d %d", dx, dy PUT;
hpos += dx;
vpos += dy;
}
OUT "\n" PUT;
break;
}
for (n = 3; cbits(pi[n]) != DRAWFCN; n++)
;
outsize = n + 1;
} else if (k < ALPHABET) {
/* try to go faster and compress output */
/* by printing nnc for small positive motion followed by c */
/* kludgery; have to make sure set all the vars too */
if (esc > 0 && esc < 100) {
oput(esc / 10 + '0');
oput(esc % 10 + '0');
oput(k);
hpos += esc;
esc = 0;
} else {
if (esc)
ptesc();
oput('c');
oput(k);
oput('\n');
}
} else {
if (esc)
ptesc();
ptchname(k);
}
if (bd) {
bd -= HOR;
if (esc += bd)
ptesc();
if (k < ALPHABET)
OUT "c%c\n", k PUT;
else
ptchname(k);
if (z)
esc -= bd;
}
esc += w;
return(outsize);
}
void ptchname(int k)
{
char *chn = chname(k);
switch (chn[0]) {
case MBchar:
OUT "c%s\n", chn+1 PUT; /* \n not needed? */
break;
case Number:
OUT "N%s\n", chn+1 PUT;
break;
case Troffchar:
OUT "C%s\n", chn+1 PUT;
break;
default:
ERROR "illegal char type %s", chn WARN;
break;
}
}
void ptflush(void) /* get us to a clean output state */
{
if (TROFF) {
/* ptesc(); but always H, no h */
hpos += esc;
OUT "\nH%d\n", hpos PUT;
esc = 0;
ptps();
ptfont();
ptlead();
}
}
void ptps(void)
{
int i, j, k;
i = xpts;
for (j = 0; i > (k = pstab[j]); j++)
if (!k) {
k = pstab[--j];
break;
}
if (!ascii)
OUT "s%d\n", k PUT; /* really should put out string rep of size */
mpts = i;
}
void ptfont(void)
{
mfont = xfont;
if (ascii)
return;
if (xfont > nfonts) {
ptfpcmd(0, fonts[xfont].longname, 0); /* Put the desired font in the
* fontcache of the filter */
OUT "f0\n" PUT; /* make sure that it gets noticed */
} else
OUT "f%d\n", xfont PUT;
}
void ptfpcmd(int f, char *s, char *longname)
{
if (f > nfonts) /* a bit risky? */
f = 0;
if (longname) {
OUT "x font %d %s %s\n", f, s, longname PUT;
} else {
OUT "x font %d %s\n", f, s PUT;
}
/* OUT "f%d\n", xfont PUT; /* need this for buggy version of adobe transcript */
/* which apparently believes that x font means */
/* to set the font, not just the position. */
}
void t_ptlead(void)
{
vpos += lead;
if (!ascii)
OUT "V%d\n", vpos PUT;
lead = 0;
}
void ptesc(void)
{
hpos += esc;
if (!ascii)
if (esc > 0) {
oput('h');
if (esc>=10 && esc<100) {
oput(esc/10 + '0');
oput(esc%10 + '0');
} else
OUT "%d", esc PUT;
} else
OUT "H%d\n", hpos PUT;
esc = 0;
}
void ptpage(int n) /* called at end of each output page, we hope */
{
int i;
if (NROFF)
return;
ptlead();
vpos = 0;
if (ascii)
return;
OUT "p%d\n", n PUT; /* new page */
for (i = 0; i <= nfonts; i++)
if (fontlab[i]) {
if (fonts[i].truename)
OUT "x font %d %s %s\n", i, fonts[i].longname, fonts[i].truename PUT;
else
OUT "x font %d %s\n", i, fonts[i].longname PUT;
}
ptps();
ptfont();
}
void pttrailer(void)
{
if (TROFF)
OUT "x trailer\n" PUT;
}
void ptstop(void)
{
if (TROFF)
OUT "x stop\n" PUT;
}
void t_ptpause(void)
{
if (ascii)
return;
ptlead();
vpos = 0;
pttrailer();
ptlead();
OUT "x pause\n" PUT;
flusho();
mpts = mfont = 0;
ptesc();
esc = po;
hpos = vpos = 0; /* probably in wrong place */
}