9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

t10.c (9444B)


      1 #include "tdef.h"
      2 #include "fns.h"
      3 #include "ext.h"
      4 
      5 /*
      6  * troff10.c
      7  * 
      8  * typesetter interface
      9  */
     10 
     11 int	vpos	 = 0;	/* absolute vertical position on page */
     12 int	hpos	 = 0;	/* ditto horizontal */
     13 
     14 extern Font fonts[MAXFONTS+1];
     15 
     16 int	Inch;
     17 int	Hor;
     18 int	Vert;
     19 int	Unitwidth;
     20 int	nfonts;
     21 
     22 
     23 
     24 void t_ptinit(void)
     25 {
     26 	int i;
     27 	char buf[100], *p;
     28 
     29 	hmot = t_hmot;
     30 	makem = t_makem;
     31 	setabs = t_setabs;
     32 	setch = t_setch;
     33 	sethl = t_sethl;
     34 	setht = t_setht;
     35 	setslant = t_setslant;
     36 	vmot = t_vmot;
     37 	xlss = t_xlss;
     38 	findft = t_findft;
     39 	width = t_width;
     40 	mchbits = t_mchbits;
     41 	ptlead = t_ptlead;
     42 	ptout = t_ptout;
     43 	ptpause = t_ptpause;
     44 	setfont = t_setfont;
     45 	setps = t_setps;
     46 	setwd = t_setwd;
     47 
     48 	/* open table for device, */
     49 	/* read in resolution, size info, font info, etc., set params */
     50 	if ((p = getenv("TYPESETTER")) != 0)
     51 		strcpy(devname, p);
     52 	if (termtab[0] == 0)
     53 		strcpy(termtab, DWBfontdir);
     54 	if (fontdir[0] == 0)
     55 		strcpy(fontdir, DWBfontdir);
     56 	if (devname[0] == 0)
     57 		strcpy(devname, TDEVNAME);
     58 	hyf = 1;
     59 	lg = 1;
     60 
     61 	sprintf(buf, "/dev%s/DESC", devname);
     62 	strcat(termtab, buf);
     63 	if (getdesc(termtab) < 0) {
     64 		ERROR "can't open DESC file %s", termtab WARN;
     65 		done3(1);
     66 	}
     67 	if (!ascii) {
     68 		OUT "x T %s\n", devname PUT;
     69 		OUT "x res %d %d %d\n", Inch, Hor, Vert PUT;
     70 		OUT "x init\n" PUT;
     71 	}
     72 	for (i = 1; i <= nfonts; i++)
     73 		setfp(i, fontlab[i], (char *) 0, 0);
     74 	sps = EM/3;	/* space size */
     75 	ics = EM;	/* insertion character space */
     76 	for (i = 0; i < (NTAB - 1) && DTAB * (i + 1) < TABMASK; i++)
     77 		tabtab[i] = DTAB * (i + 1);
     78 	tabtab[NTAB-1] = 0;
     79 	pl = 11 * INCH;			/* paper length */
     80 	po = PO;		/* page offset */
     81 	spacesz = SS;
     82 	lss = lss1 = VS;
     83 	ll = ll1 = lt = lt1 = LL;
     84 	t_specnames();	/* install names like "hyphen", etc. */
     85 }
     86 
     87 void t_specnames(void)
     88 {
     89 	int	i;
     90 
     91 	for (i = 0; spnames[i].n; i++)
     92 		*spnames[i].n = chadd(spnames[i].v, Troffchar, Install);
     93 }
     94 
     95 void t_ptout(Tchar i)
     96 {
     97 	int dv;
     98 	Tchar *k;
     99 	int temp, a, b;
    100 	int diff;
    101 
    102 	if (cbits(i) != '\n') {
    103 		if (olinep >= oline + olnsize) {
    104 			diff = olinep - oline;
    105 			olnsize += OLNSIZE;
    106 			if ((oline = (Tchar *)realloc((char *)oline, olnsize * sizeof(Tchar))) != NULL) {
    107 				if (diff && olinep)
    108 					olinep = oline + diff;
    109 			} else {
    110 				ERROR "Output line overflow." WARN;
    111 				done(2);
    112 			}
    113 		}
    114 		*olinep++ = i;
    115 		return;
    116 	}
    117 	if (olinep == oline) {
    118 		lead += lss;
    119 		return;
    120 	}
    121 
    122 	hpos = po;	/* ??? */
    123 	esc = 0;	/* ??? */
    124 	ptesc();	/* the problem is to get back to the left end of the line */
    125 	dv = 0;
    126 	for (k = oline; k < olinep; k++) {
    127 		if (ismot(*k) && isvmot(*k)) {
    128 			temp = absmot(*k);
    129 			if (isnmot(*k))
    130 				temp = -temp;
    131 			dv += temp;
    132 		}
    133 	}
    134 	if (dv) {
    135 		vflag++;
    136 		*olinep++ = makem(-dv);
    137 		vflag = 0;
    138 	}
    139 
    140 	b = dip->blss + lss;
    141 	lead += dip->blss + lss;
    142 	dip->blss = 0;
    143 	for (k = oline; k < olinep; )
    144 		k += ptout0(k);	/* now passing a pointer! */
    145 	olinep = oline;
    146 	lead += dip->alss;
    147 	a = dip->alss;
    148 	dip->alss = 0;
    149 	/*
    150 	OUT "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos PUT;
    151 */
    152 	OUT "n%d %d\n", b, a PUT;	/* be nice to chuck */
    153 }
    154 
    155 int ptout0(Tchar *pi)
    156 {
    157 	int j, k, w;
    158 	int z, dx, dy, dx2, dy2, n;
    159 	Tchar i;
    160 	int outsize;	/* size of object being printed */
    161 
    162 	w = 0;
    163 	outsize = 1;	/* default */
    164 	i = *pi;
    165 	k = cbits(i);
    166 	if (ismot(i)) {
    167 		j = absmot(i);
    168 		if (isnmot(i))
    169 			j = -j;
    170 		if (isvmot(i))
    171 			lead += j;
    172 		else 
    173 			esc += j;
    174 		return(outsize);
    175 	}
    176 	if (k == CHARHT) {
    177 		xpts = fbits(i);	/* sneaky, font bits as size bits */
    178 		if (xpts != mpts)
    179 			ptps();
    180 		OUT "x H %ld\n", sbits(i) PUT;
    181 		return(outsize);
    182 	}
    183 	if (k == SLANT) {
    184 		OUT "x S %ld\n", sfbits(i)-180 PUT;
    185 		return(outsize);
    186 	}
    187 	if (k == WORDSP) {
    188 		oput('w');
    189 		return(outsize);
    190 	}
    191 	if (sfbits(i) == oldbits) {
    192 		xfont = pfont;
    193 		xpts = ppts;
    194 	} else 
    195 		xbits(i, 2);
    196 	if (k == XON) {
    197 		extern int xon;
    198 		ptflush();	/* guarantee that everything is out */
    199 		if (esc)
    200 			ptesc();
    201 		if (xfont != mfont)
    202 			ptfont();
    203 		if (xpts != mpts)
    204 			ptps();
    205 		if (lead)
    206 			ptlead();
    207 		OUT "x X " PUT;
    208 		xon++;
    209 		for (j = 1; cbits(pi[j]) != XOFF; j++)
    210 			outascii(pi[j]);
    211 		oput('\n');
    212 		xon--;
    213 		return j+1;
    214 	}
    215 	if (k < 040 && k != DRAWFCN)
    216 		return(outsize);
    217 	j = z = 0;
    218 	if (k != DRAWFCN) {
    219 		if (widcache[k].fontpts == (xfont<<8) + xpts  && !setwdf) {
    220 			w = widcache[k].width;
    221 			bd = 0;
    222 			cs = 0;
    223 		} else
    224 			w = getcw(k);
    225 		if (cs) {
    226 			if (bd)
    227 				w += (bd - 1) * HOR;
    228 			j = (cs - w) / 2;
    229 			w = cs - j;
    230 			if (bd)
    231 				w -= (bd - 1) * HOR;
    232 		}
    233 		if (iszbit(i)) {
    234 			if (cs)
    235 				w = -j; 
    236 			else 
    237 				w = 0;
    238 			z = 1;
    239 		}
    240 	}
    241 	esc += j;
    242 	if (xfont != mfont)
    243 		ptfont();
    244 	if (xpts != mpts)
    245 		ptps();
    246 	if (lead)
    247 		ptlead();
    248 	/* put out the real character here */
    249 	if (k == DRAWFCN) {
    250 		if (esc)
    251 			ptesc();
    252 		w = 0;
    253 		dx = absmot(pi[3]);
    254 		if (isnmot(pi[3]))
    255 			dx = -dx;
    256 		dy = absmot(pi[4]);
    257 		if (isnmot(pi[4]))
    258 			dy = -dy;
    259 		switch (cbits(pi[1])) {
    260 		case DRAWCIRCLE:	/* circle */
    261 			OUT "D%c %d\n", DRAWCIRCLE, dx PUT;	/* dx is diameter */
    262 			hpos += dx;
    263 			break;
    264 		case DRAWELLIPSE:
    265 			OUT "D%c %d %d\n", DRAWELLIPSE, dx, dy PUT;
    266 			hpos += dx;
    267 			break;
    268 		case DRAWBUILD:
    269 			k = cbits(pi[2]);
    270 			OUT "D%c %d ", DRAWBUILD, dx PUT;
    271 			if (k < ALPHABET)
    272 				OUT "%c\n", k PUT;
    273 			else
    274 				ptchname(k);
    275 			hpos += dx;
    276 			break;
    277 		case DRAWLINE:	/* line */
    278 			k = cbits(pi[2]);
    279 			OUT "D%c %d %d ", DRAWLINE, dx, dy PUT;
    280 			if (k < ALPHABET)
    281 				OUT "%c\n", k PUT;
    282 			else
    283 				ptchname(k);
    284 			hpos += dx;
    285 			vpos += dy;
    286 			break;
    287 		case DRAWARC:	/* arc */
    288 			dx2 = absmot(pi[5]);
    289 			if (isnmot(pi[5]))
    290 				dx2 = -dx2;
    291 			dy2 = absmot(pi[6]);
    292 			if (isnmot(pi[6]))
    293 				dy2 = -dy2;
    294 			OUT "D%c %d %d %d %d\n", DRAWARC,
    295 				dx, dy, dx2, dy2 PUT;
    296 			hpos += dx + dx2;
    297 			vpos += dy + dy2;
    298 			break;
    299 
    300 		case 's':	/* using 's' internally to avoid .tr ~ */
    301 			pi[1] = '~';
    302 		case DRAWSPLINE:	/* spline */
    303 		default:	/* something else; copy it like spline */
    304 			OUT "D%c %d %d", (char)cbits(pi[1]), dx, dy PUT;
    305 			hpos += dx;
    306 			vpos += dy;
    307 			if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) {
    308 				/* it was somehow defective */
    309 				OUT "\n" PUT;
    310 				break;
    311 			}
    312 			for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) {
    313 				dx = absmot(pi[n]);
    314 				if (isnmot(pi[n]))
    315 					dx = -dx;
    316 				dy = absmot(pi[n+1]);
    317 				if (isnmot(pi[n+1]))
    318 					dy = -dy;
    319 				OUT " %d %d", dx, dy PUT;
    320 				hpos += dx;
    321 				vpos += dy;
    322 			}
    323 			OUT "\n" PUT;
    324 			break;
    325 		}
    326 		for (n = 3; cbits(pi[n]) != DRAWFCN; n++)
    327 			;
    328 		outsize = n + 1;
    329 	} else if (k < ALPHABET) {
    330 		/* try to go faster and compress output */
    331 		/* by printing nnc for small positive motion followed by c */
    332 		/* kludgery; have to make sure set all the vars too */
    333 		if (esc > 0 && esc < 100) {
    334 			oput(esc / 10 + '0');
    335 			oput(esc % 10 + '0');
    336 			oput(k);
    337 			hpos += esc;
    338 			esc = 0;
    339 		} else {
    340 			if (esc)
    341 				ptesc();
    342 			oput('c');
    343 			oput(k);
    344 			oput('\n');
    345 		}
    346 	} else {
    347 		if (esc)
    348 			ptesc();
    349 		ptchname(k);
    350 	}
    351 	if (bd) {
    352 		bd -= HOR;
    353 		if (esc += bd)
    354 			ptesc();
    355 		if (k < ALPHABET)
    356 			OUT "c%c\n", k PUT;
    357 		else
    358 			ptchname(k);
    359 		if (z)
    360 			esc -= bd;
    361 	}
    362 	esc += w;
    363 	return(outsize);
    364 }
    365 
    366 void ptchname(int k)
    367 {
    368 	char *chn = chname(k);
    369 
    370 	switch (chn[0]) {
    371 	case MBchar:
    372 		OUT "c%s\n", chn+1 PUT;	/* \n not needed? */
    373 		break;
    374 	case Number:
    375 		OUT "N%s\n", chn+1 PUT;
    376 		break;
    377 	case Troffchar:
    378 		OUT "C%s\n", chn+1 PUT;
    379 		break;
    380 	default:
    381 		ERROR "illegal char type %s", chn WARN;
    382 		break;
    383 	}
    384 }
    385 
    386 void ptflush(void)	/* get us to a clean output state */
    387 {
    388 	if (TROFF) {
    389 		/* ptesc(); but always H, no h */
    390 		hpos += esc;
    391 		OUT "\nH%d\n", hpos PUT;
    392 		esc = 0;
    393 		ptps();
    394 		ptfont();
    395 		ptlead();
    396 	}
    397 }
    398 
    399 void ptps(void)
    400 {
    401 	int i, j, k;
    402 
    403 	i = xpts;
    404 	for (j = 0; i > (k = pstab[j]); j++)
    405 		if (!k) {
    406 			k = pstab[--j];
    407 			break;
    408 		}
    409 	if (!ascii)
    410 		OUT "s%d\n", k PUT;	/* really should put out string rep of size */
    411 	mpts = i;
    412 }
    413 
    414 void ptfont(void)
    415 {
    416 	mfont = xfont;
    417 	if (ascii)
    418 		return;
    419 	if (xfont > nfonts) {
    420 		ptfpcmd(0, fonts[xfont].longname, 0);	/* Put the desired font in the
    421 					 * fontcache of the filter */
    422 		OUT "f0\n" PUT;	/* make sure that it gets noticed */
    423 	} else
    424 		OUT "f%d\n", xfont PUT;
    425 }
    426 
    427 void ptfpcmd(int f, char *s, char *longname)
    428 {
    429 	if (f > nfonts)		/* a bit risky? */
    430 		f = 0;
    431 	if (longname) {
    432 		OUT "x font %d %s %s\n", f, s, longname PUT;
    433 	} else {
    434 		OUT "x font %d %s\n", f, s PUT;
    435 	}
    436 /*	OUT "f%d\n", xfont PUT;	/* need this for buggy version of adobe transcript */
    437 				/* which apparently believes that x font means */
    438 				/* to set the font, not just the position. */
    439 }
    440 
    441 void t_ptlead(void)
    442 {
    443 	vpos += lead;
    444 	if (!ascii)
    445 		OUT "V%d\n", vpos PUT;
    446 	lead = 0;
    447 }
    448 
    449 void ptesc(void)
    450 {
    451 	hpos += esc;
    452 	if (!ascii)
    453 		if (esc > 0) {
    454 			oput('h');
    455 			if (esc>=10 && esc<100) {
    456 				oput(esc/10 + '0');
    457 				oput(esc%10 + '0');
    458 			} else
    459 				OUT "%d", esc PUT;
    460 		} else
    461 			OUT "H%d\n", hpos PUT;
    462 	esc = 0;
    463 }
    464 
    465 void ptpage(int n)	/* called at end of each output page, we hope */
    466 {
    467 	int i;
    468 
    469 	if (NROFF)
    470 		return;
    471 	ptlead();
    472 	vpos = 0;
    473 	if (ascii)
    474 		return;
    475 	OUT "p%d\n", n PUT;	/* new page */
    476 	for (i = 0; i <= nfonts; i++)
    477 		if (fontlab[i]) {
    478 			if (fonts[i].truename)
    479 				OUT "x font %d %s %s\n", i, fonts[i].longname, fonts[i].truename PUT;
    480 			else
    481 				OUT "x font %d %s\n", i, fonts[i].longname PUT;
    482 		}
    483 	ptps();
    484 	ptfont();
    485 }
    486 
    487 void pttrailer(void)
    488 {
    489 	if (TROFF)
    490 		OUT "x trailer\n" PUT;
    491 }
    492 
    493 void ptstop(void)
    494 {
    495 	if (TROFF)
    496 		OUT "x stop\n" PUT;
    497 }
    498 
    499 void t_ptpause(void)
    500 {
    501 	if (ascii)
    502 		return;
    503 	ptlead();
    504 	vpos = 0;
    505 	pttrailer();
    506 	ptlead();
    507 	OUT "x pause\n" PUT;
    508 	flusho();
    509 	mpts = mfont = 0;
    510 	ptesc();
    511 	esc = po;
    512 	hpos = vpos = 0;	/* probably in wrong place */
    513 }