|  | #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 */ | 
|  | } |