ref: cbe4b116989c0bfec49b9ae7a1d9a85ead6648ae
dir: /sys/src/cmd/troff/t10.c/
#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){ strncpy(devname, p, sizeof devname); devname[sizeof devname-1] = 0; } 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; snprintf(buf, sizeof 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 */ 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 %d\n", sbits(i) PUT; return(outsize); } if (k == SLANT) { OUT "x S %d\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", 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 */ }