9base

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

t6.c (15468B)


      1 /*
      2  * t6.c
      3  * 
      4  * width functions, sizes and fonts
      5  */
      6 
      7 #include "tdef.h"
      8 #include "fns.h"
      9 #include "ext.h"
     10 
     11 int	fontlab[MAXFONTS+1];
     12 int	cstab[MAXFONTS+1];
     13 int	ccstab[MAXFONTS+1];
     14 int	bdtab[MAXFONTS+1];
     15 int	sbold = 0;
     16 
     17 int
     18 t_width(Tchar j)
     19 {
     20 	int i, k;
     21 
     22 	if (iszbit(j))
     23 		return 0;
     24 	if (ismot(j)) {
     25 		if (isvmot(j))
     26 			return(0);
     27 		k = absmot(j);
     28 		if (isnmot(j))
     29 			k = -k;
     30 		return(k);
     31 	}
     32 	i = cbits(j);
     33 	if (i < ' ') {
     34 		if (i == '\b')
     35 			return(-widthp);
     36 		if (i == PRESC)
     37 			i = eschar;
     38 		else if (i == HX)
     39 			return(0);
     40 	}
     41 	if (i == ohc)
     42 		return(0);
     43 	i = trtab[i];
     44 	if (i < ' ')
     45 		return(0);
     46 	if (sfbits(j) == oldbits) {
     47 		xfont = pfont;
     48 		xpts = ppts;
     49 	} else 
     50 		xbits(j, 0);
     51 	if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf)
     52 		k = widcache[i].width;
     53 	else {
     54 		k = getcw(i);
     55 		if (bd)
     56 			k += (bd - 1) * HOR;
     57 		if (cs)
     58 			k = cs;
     59 	}
     60 	widthp = k;
     61 	return(k);
     62 }
     63 
     64 /*
     65  * clear width cache-- s means just space
     66  */
     67 void zapwcache(int s)
     68 {
     69 	int i;
     70 
     71 	if (s) {
     72 		widcache[' '].fontpts = 0;
     73 		return;
     74 	}
     75 	for (i=0; i<NWIDCACHE; i++)
     76 		widcache[i].fontpts = 0;
     77 }
     78 
     79 int
     80 onfont(int n, int f)	/* is char n on font f? */
     81 {
     82 	int i;
     83 	Font *fp = &fonts[f];
     84 	Chwid *cp, *ep;
     85 	char *np;
     86 
     87 	if (n < ALPHABET) {
     88 		if (fp->wp[n].num == n)	/* ascii at front */
     89 			return n;
     90 		else
     91 			return -1;
     92 	}
     93 	cp = &fp->wp[ALPHABET];
     94 	ep = &fp->wp[fp->nchars];
     95 	for ( ; cp < ep; cp++)	/* search others */
     96 		if (cp->num == n)
     97 			return cp - &fp->wp[0];
     98 	/* maybe it was a \N... */
     99 	np = chname(n);
    100 	if (*np == Number) {
    101 		i = atoi(np+1);		/* sscanf(np+1, "%d", &i); */
    102 		cp = &fp->wp[0];
    103 		ep = &fp->wp[fp->nchars];
    104 		for ( ; cp < ep; cp++) {	/* search others */
    105 			if (cp->code == i)
    106 				return cp - &fp->wp[0];
    107 		}
    108 		return -2;	/* a \N that doesn't have an entry */
    109 	}
    110 	return -1;	/* vanilla not found */
    111 }
    112 
    113 int
    114 getcw(int i)
    115 {
    116 	int k, n, x;
    117 	Font *fp;
    118 	int nocache = 0;
    119 	if (i < ' ')
    120 		return 0;
    121 	bd = 0;
    122 	fp = &fonts[xfont];
    123 	if (i == ' ') {	/* a blank */
    124 		k = (fp->spacewidth * spacesz + 6) / 12;
    125 		/* this nonsense because .ss cmd uses 1/36 em as its units */
    126 		/* 	and default is 12 */
    127 	} else if ((n = onfont(i, xfont)) >= 0) {	/* on this font at n */
    128 		k = fp->wp[n].wid;
    129 		if (setwdf)
    130 			numtabp[CT].val |= fp->wp[n].kern;
    131 	} else if (n == -2) {		/* \N with default width */
    132 		
    133 		k = fp->defaultwidth;
    134 	} else {			/* not on current font */
    135 		nocache = 1;
    136 		k = fp->defaultwidth;	/* default-size space */
    137 		if (smnt) {
    138 			int ii, jj;
    139 			for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) {
    140 				if ((n = onfont(i, ii)) >= 0) {
    141 					k = fonts[ii].wp[n].wid;
    142 					if (xfont == sbold)
    143 						bd = bdtab[ii];
    144 					if (setwdf)
    145 						numtabp[CT].val |= fonts[ii].wp[n].kern;
    146 					break;
    147 				}
    148 			}
    149 		}
    150 	}
    151 	if (!bd)
    152 		bd = bdtab[xfont];
    153 	if (cs = cstab[xfont]) {
    154 		nocache = 1;
    155 		if (ccs = ccstab[xfont])
    156 			x = ccs; 
    157 		else 
    158 			x = xpts;
    159 		cs = (cs * EMPTS(x)) / 36;
    160 	}
    161 	/* was (k & BYTEMASK);  since .wid is unsigned, should never happen */
    162 	if (k < 0)
    163 		ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN;
    164 	k = (k * xpts + (Unitwidth / 2)) / Unitwidth;
    165 	if (nocache|bd)
    166 		widcache[i].fontpts = 0;
    167 	else {
    168 		widcache[i].fontpts = (xfont<<8) + xpts;
    169 		widcache[i].width = k;
    170 	}
    171 	return(k);
    172 	/* Unitwidth is Units/Point, where
    173 	/* Units is the fundamental digitization
    174 	/* of the character set widths, and
    175 	/* Point is the number of goobies in a point
    176 	/* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
    177 	/* In effect, it's the size at which the widths
    178 	/* translate directly into units.
    179 	*/
    180 }
    181 
    182 void xbits(Tchar i, int bitf)
    183 {
    184 	int k;
    185 
    186 	if(TROFF) {
    187 		xfont = fbits(i);
    188 		k = sbits(i);
    189 		if(k) {
    190 			xpts = pstab[k-1];
    191 			oldbits = sfbits(i);
    192 			pfont = xfont;
    193 			ppts = xpts;
    194 			return;
    195 		}
    196 		switch(bitf) {
    197 		case 0:
    198 			xfont = font;
    199 			xpts = pts;
    200 			break;
    201 		case 1:
    202 			xfont = pfont;
    203 			xpts = ppts;
    204 			break;
    205 		case 2:
    206 			xfont = mfont;
    207 			xpts = mpts;
    208 		}
    209 	}
    210 }
    211 
    212 
    213 /* these next two functions ought to be the same in troff and nroff, */
    214 /* but the data structures they search are different. */
    215 /* silly historical problem. */
    216 
    217 
    218 Tchar t_setch(int c)
    219 {
    220 	int j;
    221 	char temp[50];
    222 	char *s;
    223 
    224 	j = 0;
    225 	s = temp;
    226 	if (c == '(') {	/* \(xx */
    227 		if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
    228 			return(0);
    229 	} else {	/* \C'...' */
    230 		c = getach();
    231 		while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1)
    232 			s++;
    233 	}
    234 	*s = '\0';
    235 #ifdef UNICODE
    236 	return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */
    237 #else
    238 	if (NROFF) {
    239 		j = chadd(temp, Troffchar, Lookup);
    240 		if ( j == -1)
    241 			return 0;
    242 		else
    243 			return j | chbits;
    244 	} else
    245 		return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */
    246 		
    247 #endif /*UNICODE*/
    248 }
    249 
    250 Tchar t_setabs(void)		/* set absolute char from \N'...' */
    251 {
    252 	int n;
    253 	char temp[10];
    254 
    255 	getch();	/* delim */
    256 	n = 0;
    257 	n = inumb(&n);
    258 	getch();	/* delim */
    259 	if (nonumb)
    260 		return 0;
    261 	sprintf(temp, "%d", n);	/* convert into "#n" */
    262 	n = chadd(temp, Number, Install);
    263 	return n | chbits;
    264 }
    265 
    266 
    267 /*
    268  * fontlab[] is a cache that contains font information
    269  * for each font.
    270  * fontlab[] contains the 1- or 2-character name of the
    271  * font current associated with that font.
    272  * fonts 1..nfonts correspond to the mounted fonts;
    273  * the last of these are the special fonts.
    274  * If we don't use the (named) font in one of the
    275  * standard positions, we install the name in the next
    276  * free slot of fontlab[] and font[].
    277  * Whenever we need info about the font, we
    278  * read in the data into the next free slot with getfont.
    279  * The ptfont() (t10.c) routine will tell
    280  * the device filter to put the font always at position
    281  * zero if xfont > nfonts, so no need to change these filters.
    282  * Yes, this is a bit kludgy.
    283  *
    284  * This gives the new specs of findft:
    285  * 	find the font name i, where i also can be a number.
    286  * 	Installs the font(name) i when not present
    287  * 	returns -1 on error
    288  */
    289 
    290 int
    291 t_findft(int i)
    292 {
    293 	int k;
    294 	Uchar *p;
    295 
    296 	p = unpair(i);
    297 
    298 	if (isdigit(p[0])) {		/* first look for numbers */
    299 		k = p[0] - '0';
    300 		if (p[1] > 0 && isdigit(p[1]))
    301 			k = 10 * k + p[1] - '0';
    302 		if (k > 0 && k <= nfonts && k < smnt)
    303 			return(k);	/* mounted font:  .ft 3 */
    304 		if (fontlab[k] && k <= MAXFONTS) {	/* translate */
    305 			return(k);			/*number to a name */
    306 		} else {
    307 			fprintf(stderr, "troff: no font at position %d\n", k);
    308 			return(-1);	/* wild number */
    309 		}
    310 	}
    311 
    312 	/*
    313 	 * Now we look for font names
    314 	 */
    315 	for (k = 1; fontlab[k] != i; k++) {
    316 		if (k > MAXFONTS)
    317 			return(-1);	/* running out of fontlab space */
    318 		if (fontlab[k] == 0) {	/* passed all existing names */
    319 			if (setfp(k, i, (char *) 0, 1) == -1)
    320 				return(-1);
    321 			else {
    322 				fontlab[k] = i;	/* install the name */
    323 				return(k);
    324 			}
    325 		}
    326 	}
    327 	return(k);			/* was one of the existing names */
    328 }
    329 
    330 
    331 void caseps(void)
    332 {
    333 	int i;
    334 
    335 	if (TROFF) {
    336 		if(skip())
    337 			i = apts1;
    338 		else {
    339 			noscale++;
    340 			i = inumb(&apts);	/* this is a disaster for fractional point sizes */
    341 			noscale = 0;
    342 			if(nonumb)
    343 				i = apts1;
    344 		}
    345 		casps1(i);
    346 	}
    347 }
    348 
    349 
    350 void casps1(int i)
    351 {
    352 
    353 /*
    354  * in olden times, it used to ignore changes to 0 or negative.
    355  * this is meant to allow the requested size to be anything,
    356  * in particular so eqn can generate lots of \s-3's and still
    357  * get back by matching \s+3's.
    358 
    359 	if (i <= 0)
    360 		return;
    361 */
    362 	apts1 = apts;
    363 	apts = i;
    364 	pts1 = pts;
    365 	pts = findps(i);
    366 	mchbits();
    367 }
    368 
    369 int
    370 findps(int i)
    371 {
    372 	int j, k;
    373 
    374 	for (j=k=0 ; pstab[j] != 0 ; j++)
    375 		if (abs(pstab[j]-i) < abs(pstab[k]-i))
    376 			k = j;
    377 
    378 	return(pstab[k]);
    379 }
    380 
    381 
    382 void t_mchbits(void)
    383 {
    384 	int i, j, k;
    385 
    386 	i = pts;
    387 	for (j = 0; i > (k = pstab[j]); j++)
    388 		if (!k) {
    389 			j--;
    390 			break;
    391 		}
    392 	chbits = 0;
    393 	setsbits(chbits, ++j);
    394 	setfbits(chbits, font);
    395 	sps = width(' ' | chbits);
    396 	zapwcache(1);
    397 }
    398 
    399 void t_setps(void)
    400 {
    401 	int i, j;
    402 
    403 	j = 0;
    404 	i = cbits(getch());
    405 	if (isdigit(i)) {		/* \sd or \sdd */
    406 		i -= '0';
    407 		if (i == 0)		/* \s0 */
    408 			j = apts1;
    409 		else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) {	/* \sdd */
    410 			j = 10 * i + j - '0';
    411 			ch = 0;
    412 		} else		/* \sd */
    413 			j = i;
    414 	} else if (i == '(') {		/* \s(dd */
    415 		j = cbits(getch()) - '0';
    416 		j = 10 * j + cbits(getch()) - '0';
    417 		if (j == 0)		/* \s(00 */
    418 			j = apts1;
    419 	} else if (i == '+' || i == '-') {	/* \s+, \s- */
    420 		j = cbits(getch());
    421 		if (isdigit(j)) {		/* \s+d, \s-d */
    422 			j -= '0';
    423 		} else if (j == '(') {		/* \s+(dd, \s-(dd */
    424 			j = cbits(getch()) - '0';
    425 			j = 10 * j + cbits(getch()) - '0';
    426 		}
    427 		if (i == '-')
    428 			j = -j;
    429 		j += apts;
    430 	}
    431 	casps1(j);
    432 }
    433 
    434 
    435 Tchar t_setht(void)		/* set character height from \H'...' */
    436 {
    437 	int n;
    438 	Tchar c;
    439 
    440 	getch();
    441 	n = inumb(&apts);
    442 	getch();
    443 	if (n == 0 || nonumb)
    444 		n = apts;	/* does this work? */
    445 	c = CHARHT;
    446 	c |= ZBIT;
    447 	setsbits(c, n);
    448 	setfbits(c, pts);	/* sneaky, CHARHT font bits are size bits */
    449 	return(c);
    450 }
    451 
    452 Tchar t_setslant(void)		/* set slant from \S'...' */
    453 {
    454 	int n;
    455 	Tchar c;
    456 
    457 	getch();
    458 	n = 0;
    459 	n = inumb(&n);
    460 	getch();
    461 	if (nonumb)
    462 		n = 0;
    463 	c = SLANT;
    464 	c |= ZBIT;
    465 	setsfbits(c, n+180);
    466 	return(c);
    467 }
    468 
    469 
    470 void caseft(void)
    471 {
    472 	if (!TROFF) {
    473 		n_caseft();
    474 		return;
    475 	}
    476 	skip();
    477 	setfont(1);
    478 }
    479 
    480 
    481 void t_setfont(int a)
    482 {
    483 	int i, j;
    484 
    485 	if (a)
    486 		i = getrq();
    487 	else 
    488 		i = getsn();
    489 	if (!i || i == 'P') {
    490 		j = font1;
    491 		goto s0;
    492 	}
    493 	if (/* i == 'S' || */ i == '0')	/* an experiment -- why can't we change to it? */
    494 		return;
    495 	if ((j = findft(i)) == -1)
    496 		if ((j = setfp(0, i, (char*) 0, 1)) == -1)	/* try to put it in position 0 */
    497 			return;
    498 s0:
    499 	font1 = font;
    500 	font = j;
    501 	mchbits();
    502 }
    503 
    504 
    505 void t_setwd(void)
    506 {
    507 	int base, wid;
    508 	Tchar i;
    509 	int delim, emsz, k;
    510 	int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
    511 
    512 	base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0;
    513 	if (ismot(i = getch()))
    514 		return;
    515 	delim = cbits(i);
    516 	savhp = numtabp[HP].val;
    517 	numtabp[HP].val = 0;
    518 	savapts = apts;
    519 	savapts1 = apts1;
    520 	savfont = font;
    521 	savfont1 = font1;
    522 	savpts = pts;
    523 	savpts1 = pts1;
    524 	setwdf++;
    525 	while (cbits(i = getch()) != delim && !nlflg) {
    526 		k = width(i);
    527 		wid += k;
    528 		numtabp[HP].val += k;
    529 		if (!ismot(i)) {
    530 			emsz = (INCH/72) * xpts;
    531 		} else if (isvmot(i)) {
    532 			k = absmot(i);
    533 			if (isnmot(i))
    534 				k = -k;
    535 			base -= k;
    536 			emsz = 0;
    537 		} else 
    538 			continue;
    539 		if (base < numtabp[SB].val)
    540 			numtabp[SB].val = base;
    541 		if ((k = base + emsz) > numtabp[ST].val)
    542 			numtabp[ST].val = k;
    543 	}
    544 	setn1(wid, 0, (Tchar) 0);
    545 	numtabp[HP].val = savhp;
    546 	apts = savapts;
    547 	apts1 = savapts1;
    548 	font = savfont;
    549 	font1 = savfont1;
    550 	pts = savpts;
    551 	pts1 = savpts1;
    552 	mchbits();
    553 	setwdf = 0;
    554 }
    555 
    556 
    557 Tchar t_vmot(void)
    558 {
    559 	dfact = lss;
    560 	vflag++;
    561 	return t_mot();
    562 }
    563 
    564 
    565 Tchar t_hmot(void)
    566 {
    567 	dfact = EM;
    568 	return t_mot();
    569 }
    570 
    571 
    572 Tchar t_mot(void)
    573 {
    574 	int j, n;
    575 	Tchar i;
    576 
    577 	j = HOR;
    578 	getch(); /*eat delim*/
    579 	if (n = atoi0()) {
    580 		if (vflag)
    581 			j = VERT;
    582 		i = makem(quant(n, j));
    583 	} else
    584 		i = 0;
    585 	getch();
    586 	vflag = 0;
    587 	dfact = 1;
    588 	return(i);
    589 }
    590 
    591 
    592 Tchar t_sethl(int k)
    593 {
    594 	int j;
    595 	Tchar i;
    596 
    597 	j = EM / 2;
    598 	if (k == 'u')
    599 		j = -j;
    600 	else if (k == 'r')
    601 		j = -2 * j;
    602 	vflag++;
    603 	i = makem(j);
    604 	vflag = 0;
    605 	return(i);
    606 }
    607 
    608 
    609 Tchar t_makem(int i)
    610 {
    611 	Tchar j;
    612 
    613 	if (i >= 0)
    614 		j = i;
    615 	else
    616 		j = -i;
    617 	if (Hor > 1 && !vflag)
    618 		j = (j + Hor/2)/Hor * Hor;
    619 	j |= MOT;
    620 	if (i < 0)
    621 		j |= NMOT;
    622 	if (vflag)
    623 		j |= VMOT;
    624 	return(j);
    625 }
    626 
    627 
    628 Tchar getlg(Tchar i)
    629 {
    630 	Tchar j, k;
    631 	int lf;
    632 
    633 	if (!TROFF)
    634 		return i;
    635 	if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */
    636 		return(i);
    637 	j = getch0();
    638 	if (cbits(j) == 'i' && (lf & LFI))
    639 		j = LIG_FI;
    640 	else if (cbits(j) == 'l' && (lf & LFL))
    641 		j = LIG_FL;
    642 	else if (cbits(j) == 'f' && (lf & LFF)) {
    643 		if ((lf & (LFFI|LFFL)) && lg != 2) {
    644 			k = getch0();
    645 			if (cbits(k)=='i' && (lf&LFFI))
    646 				j = LIG_FFI;
    647 			else if (cbits(k)=='l' && (lf&LFFL))
    648 				j = LIG_FFL;
    649 			else {
    650 				*pbp++ = k;
    651 				j = LIG_FF;
    652 			}
    653 		} else 
    654 			j = LIG_FF;
    655 	} else {
    656 		*pbp++ = j;
    657 		j = i;
    658 	}
    659 	return(i & SFMASK | j);
    660 }
    661 
    662 
    663 void caselg(void)
    664 {
    665 
    666 	if(TROFF) {
    667 		skip();
    668 		lg = atoi0();
    669 		if (nonumb)
    670 			lg = 1;
    671 	}
    672 }
    673 
    674 void casefp(void)
    675 {
    676 	int i, j;
    677 
    678 	if (!TROFF) {
    679 		n_casefp();
    680 		return;
    681 	}
    682 	skip();
    683 	i = cbits(getch());
    684 	if (isdigit(i)) {
    685 		i -= '0';
    686 		j = cbits(getch());
    687 		if (isdigit(j))
    688 			i = 10 * i + j - '0';
    689 	}
    690 	if (i <= 0 || i > nfonts)
    691 		ERROR "fp: bad font position %d", i WARN;
    692 	else if (skip() || !(j = getrq()))
    693 		ERROR "fp: no font name" WARN; 
    694 	else if (skip() || !getname())
    695 		setfp(i, j, (char*) 0, 1);
    696 	else		/* 3rd argument = filename */
    697 		setfp(i, j, nextf, 1);
    698 }
    699 
    700 char *strdupl(const char *s)	/* make a copy of s */
    701 {
    702 	char *t;
    703 
    704 	t = (char *) malloc(strlen(s) + 1);
    705 	if (t == NULL)
    706 		ERROR "out of space in strdupl(%s)", s FATAL;
    707 	strcpy(t, s);
    708 	return t;
    709 }
    710 
    711 int
    712 setfp(int pos, int f, char *truename, int print)	/* mount font f at position pos[0...nfonts] */
    713 {
    714 	char pathname[NS], shortname[NS], *sl;
    715 
    716 	sl = (char*)0;
    717 	zapwcache(0);
    718 	if (truename)
    719 		strcpy(shortname, truename);
    720 	else
    721 		strcpy(shortname, (char *) unpair(f));
    722 	if (truename && strrchr(truename, '/')) {	/* .fp 1 R dir/file: use verbatim */
    723 		sprintf(pathname, "%s", truename);
    724 		if (fonts[pos].truename)
    725 			free(fonts[pos].truename);
    726 		fonts[pos].truename = strdupl(truename);
    727 	} else if (truename) {			/* synonym: .fp 1 R Avant */
    728 		sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename);
    729 		truename = 0;	/* so doesn't get repeated by ptfpcmd */
    730 	} else					/* vanilla: .fp 5 XX */
    731 		sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname);
    732 	if (truename == 0 && fonts[pos].truename != 0) {
    733 		free(fonts[pos].truename);
    734 		fonts[pos].truename = 0;
    735 	}
    736 	if (getfont(pathname, pos) < 0) {
    737 		ERROR "Can't open font file %s", pathname WARN;
    738 		return -1;
    739 	}
    740 	if (print && !ascii) {
    741 		ptfpcmd(pos, fonts[pos].longname, truename);
    742 		ptfont();
    743 	}
    744 	if (pos == smnt) {
    745 		smnt = 0; 
    746 		sbold = 0; 
    747 	}
    748 	fontlab[pos] = f;
    749 	if (smnt == 0 && fonts[pos].specfont)
    750 		smnt = pos;
    751 	bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
    752 	return pos;
    753 }
    754 
    755 /*
    756  * .cs request; don't check legality of optional arguments
    757  */
    758 void casecs(void)
    759 {
    760 	int i, j;
    761 
    762 	if (TROFF) {
    763 		int savtr = trace;
    764 
    765 		trace = 0;
    766 		noscale++;
    767 		skip();
    768 		if (!(i = getrq()) || (i = findft(i)) < 0)
    769 			goto rtn;
    770 		skip();
    771 		cstab[i] = atoi0();
    772 		skip();
    773 		j = atoi0();
    774 		if(nonumb)
    775 			ccstab[i] = 0;
    776 		else
    777 			ccstab[i] = findps(j);
    778 	rtn:
    779 		zapwcache(0);
    780 		noscale = 0;
    781 		trace = savtr;
    782 	}
    783 }
    784 
    785 
    786 void casebd(void)
    787 {
    788 	int i, j, k;
    789 
    790 	j=0;
    791 	if (!TROFF) {
    792 		n_casebd();
    793 		return;
    794 	}
    795 	zapwcache(0);
    796 	k = 0;
    797 bd0:
    798 	if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
    799 		if (k)
    800 			goto bd1;
    801 		else 
    802 			return;
    803 	}
    804 	if (j == smnt) {
    805 		k = smnt;
    806 		goto bd0;
    807 	}
    808 	if (k) {
    809 		sbold = j;
    810 		j = k;
    811 	}
    812 bd1:
    813 	skip();
    814 	noscale++;
    815 	bdtab[j] = atoi0();
    816 	noscale = 0;
    817 }
    818 
    819 
    820 void casevs(void)
    821 {
    822 	int i;
    823 
    824 	if (!TROFF) {
    825 		n_casevs();
    826 		return;
    827 	}
    828 	skip();
    829 	vflag++;
    830 	dfact = INCH; /* default scaling is points! */
    831 	dfactd = 72;
    832 	res = VERT;
    833 	i = inumb(&lss);
    834 	if (nonumb)
    835 		i = lss1;
    836 	if (i < VERT) 
    837 		i = VERT;
    838 	lss1 = lss;
    839 	lss = i;
    840 }
    841 
    842 
    843 void casess(void)
    844 {
    845 	int i;
    846 
    847 	if(TROFF) {
    848 		noscale++;
    849 		skip();
    850 		if(i = atoi0()) {
    851 			spacesz = i & 0177;
    852 			zapwcache(0);
    853 			sps = width(' ' | chbits);
    854 		}
    855 		noscale = 0;
    856 	}
    857 }
    858 
    859 
    860 Tchar t_xlss(void)
    861 {
    862 	/* stores \x'...' into two successive Tchars.
    863 	/* the first contains HX, the second the value,
    864 	/* encoded as a vertical motion.
    865 	/* decoding is done in n2.c by pchar().
    866 	*/
    867 	int i;
    868 
    869 	getch();
    870 	dfact = lss;
    871 	i = quant(atoi0(), VERT);
    872 	dfact = 1;
    873 	getch();
    874 	if (i >= 0)
    875 		*pbp++ = MOT | VMOT | i;
    876 	else
    877 		*pbp++ = MOT | VMOT | NMOT | -i;
    878 	return(HX);
    879 }
    880 
    881 Uchar *unpair(int i)
    882 {
    883 	static Uchar name[3];
    884 
    885 	name[0] = i & SHORTMASK;
    886 	name[1] = (i >> SHORT) & SHORTMASK;
    887 	name[2] = 0;
    888 	return name;
    889 }