9base

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

n5.c (14292B)


      1 /*
      2  * troff5.c
      3  * 
      4  * misc processing requests
      5  */
      6 
      7 #include "tdef.h"
      8 #include "fns.h"
      9 #include "ext.h"
     10 
     11 int	iflist[NIF];
     12 int	ifx;
     13 int	ifnum = 0;	/* trying numeric expression for .if or .ie condition */
     14 
     15 void casead(void)
     16 {
     17 	int i;
     18 
     19 	ad = 1;
     20 	/* leave admod alone */
     21 	if (skip())
     22 		return;
     23 	switch (i = cbits(getch())) {
     24 	case 'r':	/* right adj, left ragged */
     25 		admod = 2;
     26 		break;
     27 	case 'l':	/* left adj, right ragged */
     28 		admod = ad = 0;	/* same as casena */
     29 		break;
     30 	case 'c':	/*centered adj*/
     31 		admod = 1;
     32 		break;
     33 	case 'b': 
     34 	case 'n':
     35 		admod = 0;
     36 		break;
     37 	case '0': 
     38 	case '2': 
     39 	case '4':
     40 		ad = 0;
     41 	case '1': 
     42 	case '3': 
     43 	case '5':
     44 		admod = (i - '0') / 2;
     45 	}
     46 }
     47 
     48 
     49 void casena(void)
     50 {
     51 	ad = 0;
     52 }
     53 
     54 
     55 void casefi(void)
     56 {
     57 	tbreak();
     58 	fi = 1;
     59 	pendnf = 0;
     60 }
     61 
     62 
     63 void casenf(void)
     64 {
     65 	tbreak();
     66 	fi = 0;
     67 }
     68 
     69 
     70 void casers(void)
     71 {
     72 	dip->nls = 0;
     73 }
     74 
     75 
     76 void casens(void)
     77 {
     78 	dip->nls++;
     79 }
     80 
     81 int
     82 chget(int c)
     83 {
     84 	Tchar i;
     85 
     86 	i = 0;
     87 	if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
     88 		ch = i;
     89 		return(c);
     90 	} else 
     91 		return cbits(i);	/* was (i & BYTEMASK) */
     92 }
     93 
     94 
     95 void casecc(void)
     96 {
     97 	cc = chget('.');
     98 }
     99 
    100 
    101 void casec2(void)
    102 {
    103 	c2 = chget('\'');
    104 }
    105 
    106 
    107 void casehc(void)
    108 {
    109 	ohc = chget(OHC);
    110 }
    111 
    112 
    113 void casetc(void)
    114 {
    115 	tabc = chget(0);
    116 }
    117 
    118 
    119 void caselc(void)
    120 {
    121 	dotc = chget(0);
    122 }
    123 
    124 
    125 void casehy(void)
    126 {
    127 	int i;
    128 
    129 	hyf = 1;
    130 	if (skip())
    131 		return;
    132 	noscale++;
    133 	i = atoi0();
    134 	noscale = 0;
    135 	if (nonumb)
    136 		return;
    137 	hyf = max(i, 0);
    138 }
    139 
    140 
    141 void casenh(void)
    142 {
    143 	hyf = 0;
    144 }
    145 
    146 int
    147 max(int aa, int bb)
    148 {
    149 	if (aa > bb)
    150 		return(aa);
    151 	else 
    152 		return(bb);
    153 }
    154 
    155 
    156 void casece(void)
    157 {
    158 	int i;
    159 
    160 	noscale++;
    161 	skip();
    162 	i = max(atoi0(), 0);
    163 	if (nonumb)
    164 		i = 1;
    165 	tbreak();
    166 	ce = i;
    167 	noscale = 0;
    168 }
    169 
    170 
    171 void casein(void)
    172 {
    173 	int i;
    174 
    175 	if (skip())
    176 		i = in1;
    177 	else {
    178 		i = max(hnumb(&in), 0);
    179 		if (nonumb)
    180 			i = in1;
    181 	}
    182 	tbreak();
    183 	in1 = in;
    184 	in = i;
    185 	if (!nc) {
    186 		un = in;
    187 		setnel();
    188 	}
    189 }
    190 
    191 
    192 void casell(void)
    193 {
    194 	int i;
    195 
    196 	if (skip())
    197 		i = ll1;
    198 	else {
    199 		i = max(hnumb(&ll), INCH / 10);
    200 		if (nonumb)
    201 			i = ll1;
    202 	}
    203 	ll1 = ll;
    204 	ll = i;
    205 	setnel();
    206 }
    207 
    208 
    209 void caselt(void)
    210 {
    211 	int i;
    212 
    213 	if (skip())
    214 		i = lt1;
    215 	else {
    216 		i = max(hnumb(&lt), 0);
    217 		if (nonumb)
    218 			i = lt1;
    219 	}
    220 	lt1 = lt;
    221 	lt = i;
    222 }
    223 
    224 
    225 void caseti(void)
    226 {
    227 	int i;
    228 
    229 	if (skip())
    230 		return;
    231 	i = max(hnumb(&in), 0);
    232 	tbreak();
    233 	un1 = i;
    234 	setnel();
    235 }
    236 
    237 
    238 void casels(void)
    239 {
    240 	int i;
    241 
    242 	noscale++;
    243 	if (skip())
    244 		i = ls1;
    245 	else {
    246 		i = max(inumb(&ls), 1);
    247 		if (nonumb)
    248 			i = ls1;
    249 	}
    250 	ls1 = ls;
    251 	ls = i;
    252 	noscale = 0;
    253 }
    254 
    255 
    256 void casepo(void)
    257 {
    258 	int i;
    259 
    260 	if (skip())
    261 		i = po1;
    262 	else {
    263 		i = max(hnumb(&po), 0);
    264 		if (nonumb)
    265 			i = po1;
    266 	}
    267 	po1 = po;
    268 	po = i;
    269 	if (TROFF & !ascii)
    270 		esc += po - po1;
    271 }
    272 
    273 
    274 void casepl(void)
    275 {
    276 	int i;
    277 
    278 	skip();
    279 	if ((i = vnumb(&pl)) == 0)
    280 		pl = 11 * INCH; /*11in*/
    281 	else 
    282 		pl = i;
    283 	if (numtabp[NL].val > pl)
    284 		numtabp[NL].val = pl;
    285 }
    286 
    287 
    288 void casewh(void)
    289 {
    290 	int i, j, k;
    291 
    292 	lgf++;
    293 	skip();
    294 	i = vnumb((int *)0);
    295 	if (nonumb)
    296 		return;
    297 	skip();
    298 	j = getrq();
    299 	if ((k = findn(i)) != NTRAP) {
    300 		mlist[k] = j;
    301 		return;
    302 	}
    303 	for (k = 0; k < NTRAP; k++)
    304 		if (mlist[k] == 0)
    305 			break;
    306 	if (k == NTRAP) {
    307 		flusho();
    308 		ERROR "cannot plant trap." WARN;
    309 		return;
    310 	}
    311 	mlist[k] = j;
    312 	nlist[k] = i;
    313 }
    314 
    315 
    316 void casech(void)
    317 {
    318 	int i, j, k;
    319 
    320 	lgf++;
    321 	skip();
    322 	if (!(j = getrq()))
    323 		return;
    324 	else 
    325 		for (k = 0; k < NTRAP; k++)
    326 			if (mlist[k] == j)
    327 				break;
    328 	if (k == NTRAP)
    329 		return;
    330 	skip();
    331 	i = vnumb((int *)0);
    332 	if (nonumb)
    333 		mlist[k] = 0;
    334 	nlist[k] = i;
    335 }
    336 
    337 int
    338 findn(int i)
    339 {
    340 	int k;
    341 
    342 	for (k = 0; k < NTRAP; k++)
    343 		if ((nlist[k] == i) && (mlist[k] != 0))
    344 			break;
    345 	return(k);
    346 }
    347 
    348 
    349 void casepn(void)
    350 {
    351 	int i;
    352 
    353 	skip();
    354 	noscale++;
    355 	i = max(inumb(&numtabp[PN].val), 0);
    356 	noscale = 0;
    357 	if (!nonumb) {
    358 		npn = i;
    359 		npnflg++;
    360 	}
    361 }
    362 
    363 
    364 void casebp(void)
    365 {
    366 	int i;
    367 	Stack *savframe;
    368 
    369 	if (dip != d)
    370 		return;
    371 	savframe = frame;
    372 	skip();
    373 	if ((i = inumb(&numtabp[PN].val)) < 0)
    374 		i = 0;
    375 	tbreak();
    376 	if (!nonumb) {
    377 		npn = i;
    378 		npnflg++;
    379 	} else if (dip->nls)
    380 		return;
    381 	eject(savframe);
    382 }
    383 
    384 void casetm(void)
    385 {
    386 	casetm1(0, stderr);
    387 }
    388 
    389 
    390 void casefm(void)
    391 {
    392 	static struct fcache {
    393 		char *name;
    394 		FILE *fp;
    395 	} fcache[15];
    396 	int i;
    397 
    398 	if ( skip() || !getname()) {
    399 		ERROR "fm: missing filename" WARN;
    400 		return;
    401 	}
    402 		
    403 	for (i = 0; i < 15 && fcache[i].fp != NULL; i++) {
    404 		if (strcmp(nextf, fcache[i].name) == 0)
    405 			break;
    406 	}
    407 	if (i >= 15) {
    408 		ERROR "fm: too many streams" WARN;
    409 		return;
    410 	}
    411 	if (fcache[i].fp == NULL) {
    412 		if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) {
    413 			ERROR "fm: cannot open %s", nextf WARN;
    414 			return;
    415 		}
    416 		fcache[i].name = strdupl(nextf);
    417 	}
    418 	casetm1(0, fcache[i].fp);
    419 }
    420 
    421 void casetm1(int ab, FILE *out) 
    422 {
    423 	int i, j, c;
    424 	char *p;
    425 	char tmbuf[NTM];
    426 
    427 	lgf++;
    428 	copyf++;
    429 	if (ab) {
    430 		if (skip())
    431 			ERROR "User Abort" WARN;
    432 		else {
    433 			extern int error;
    434 			int savtrac = trace;
    435 			i = trace = 0;
    436 			noscale++;
    437 			i = inumb(&trace);
    438 			noscale--;
    439 			if (i) {
    440 				error = i;
    441 				if (nlflg || skip())
    442 					ERROR "User Abort, exit code %d", i WARN;
    443 			}
    444 			trace = savtrac;
    445 		}
    446 	} else
    447 		skip();	
    448 	for (i = 0; i < NTM - 2; ) {
    449 		if ((c = cbits(getch())) == '\n' || c == RIGHT)
    450 			break;
    451 		else if (c == MINUS) {	/* special pleading for strange encodings */
    452 			tmbuf[i++] = '\\';
    453 			tmbuf[i++] = '-';
    454 		} else if (c == PRESC) {
    455 			tmbuf[i++] = '\\';
    456 			tmbuf[i++] = 'e';
    457 		} else if (c == FILLER) {
    458 			tmbuf[i++] = '\\';
    459 			tmbuf[i++] = '&';
    460 		} else if (c == UNPAD) {
    461 			tmbuf[i++] = '\\';
    462 			tmbuf[i++] = ' ';
    463 		} else if (c == OHC) {
    464 			tmbuf[i++] = '\\';
    465 			tmbuf[i++] = '%';
    466 		} else if (c >= ALPHABET) {
    467 			p = chname(c);
    468 			switch (*p) {
    469 			case MBchar:
    470 				strcpy(&tmbuf[i], p+1);
    471 				break;
    472 			case Number:
    473 				sprintf(&tmbuf[i], "\\N'%s'", p+1);
    474 				break;
    475 			case Troffchar:
    476 				if ((j = strlen(p+1)) == 2)
    477 					sprintf(&tmbuf[i], "\\(%s", p+1);
    478 				else
    479 					sprintf(&tmbuf[i], "\\C'%s'", p+1);
    480 				break;
    481 			default:
    482 				sprintf(&tmbuf[i]," %s? ", p);
    483 				break;
    484 			}
    485 			j = strlen(&tmbuf[i]);
    486 			i += j;
    487 		} else
    488 			tmbuf[i++] = c;
    489 	}
    490 	tmbuf[i] = 0;
    491 	if (ab)	/* truncate output */
    492 		obufp = obuf;	/* should be a function in n2.c */
    493 	flusho();
    494 	if (i)
    495 		fprintf(out, "%s\n", tmbuf);
    496 	fflush(out);
    497 	copyf--;
    498 	lgf--;
    499 }
    500 
    501 
    502 void casesp(void)
    503 {
    504 	casesp1(0);
    505 }
    506 
    507 void casesp1(int a)
    508 {
    509 	int i, j, savlss;
    510 
    511 	tbreak();
    512 	if (dip->nls || trap)
    513 		return;
    514 	i = findt1();
    515 	if (!a) {
    516 		skip();
    517 		j = vnumb((int *)0);
    518 		if (nonumb)
    519 			j = lss;
    520 	} else 
    521 		j = a;
    522 	if (j == 0)
    523 		return;
    524 	if (i < j)
    525 		j = i;
    526 	savlss = lss;
    527 	if (dip != d)
    528 		i = dip->dnl; 
    529 	else 
    530 		i = numtabp[NL].val;
    531 	if ((i + j) < 0)
    532 		j = -i;
    533 	lss = j;
    534 	newline(0);
    535 	lss = savlss;
    536 }
    537 
    538 
    539 void casert(void)
    540 {
    541 	int a, *p;
    542 
    543 	skip();
    544 	if (dip != d)
    545 		p = &dip->dnl; 
    546 	else 
    547 		p = &numtabp[NL].val;
    548 	a = vnumb(p);
    549 	if (nonumb)
    550 		a = dip->mkline;
    551 	if ((a < 0) || (a >= *p))
    552 		return;
    553 	nb++;
    554 	casesp1(a - *p);
    555 }
    556 
    557 
    558 void caseem(void)
    559 {
    560 	lgf++;
    561 	skip();
    562 	em = getrq();
    563 }
    564 
    565 
    566 void casefl(void)
    567 {
    568 	tbreak();
    569 	if (!ascii)
    570 		ptflush();
    571 	flusho();
    572 }
    573 
    574 
    575 void caseev(void)
    576 {
    577 	int nxev;
    578 
    579 	if (skip()) {
    580 e0:
    581 		if (evi == 0)
    582 			return;
    583 		nxev =  evlist[--evi];
    584 		goto e1;
    585 	}
    586 	noscale++;
    587 	nxev = atoi0();
    588 	noscale = 0;
    589 	if (nonumb)
    590 		goto e0;
    591 	flushi();
    592 	if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) {
    593 		flusho();
    594 		ERROR "cannot do .ev %d", nxev WARN;
    595 		if (error)
    596 			done2(040);
    597 		else 
    598 			edone(040);
    599 		return;
    600 	}
    601 	evlist[evi++] = ev;
    602 e1:
    603 	if (ev == nxev)
    604 		return;
    605 	ev = nxev;
    606 	envp = &env[ev];
    607 }
    608 
    609 void envcopy(Env *e1, Env *e2)	/* copy env e2 to e1 */
    610 {
    611 	*e1 = *e2;	/* rumor hath that this fails on some machines */
    612 }
    613 
    614 
    615 void caseel(void)
    616 {
    617 	if (--ifx < 0) {
    618 		ifx = 0;
    619 		iflist[0] = 0;
    620 	}
    621 	caseif1(2);
    622 }
    623 
    624 
    625 void caseie(void)
    626 {
    627 	if (ifx >= NIF) {
    628 		ERROR "if-else overflow." WARN;
    629 		ifx = 0;
    630 		edone(040);
    631 	}
    632 	caseif1(1);
    633 	ifx++;
    634 }
    635 
    636 
    637 void caseif(void)
    638 {
    639 	caseif1(0);
    640 }
    641 
    642 void caseif1(int x)
    643 {
    644 	extern int falsef;
    645 	int notflag, true;
    646 	Tchar i;
    647 
    648 	if (x == 2) {
    649 		notflag = 0;
    650 		true = iflist[ifx];
    651 		goto i1;
    652 	}
    653 	true = 0;
    654 	skip();
    655 	if ((cbits(i = getch())) == '!') {
    656 		notflag = 1;
    657 	} else {
    658 		notflag = 0;
    659 		ch = i;
    660 	}
    661 	ifnum++;
    662 	i = atoi0();
    663 	ifnum = 0;
    664 	if (!nonumb) {
    665 		if (i > 0)
    666 			true++;
    667 		goto i1;
    668 	}
    669 	i = getch();
    670 	switch (cbits(i)) {
    671 	case 'e':
    672 		if (!(numtabp[PN].val & 01))
    673 			true++;
    674 		break;
    675 	case 'o':
    676 		if (numtabp[PN].val & 01)
    677 			true++;
    678 		break;
    679 	case 'n':
    680 		if (NROFF)
    681 			true++;
    682 		break;
    683 	case 't':
    684 		if (TROFF)
    685 			true++;
    686 		break;
    687 	case ' ':
    688 		break;
    689 	default:
    690 		true = cmpstr(i);
    691 	}
    692 i1:
    693 	true ^= notflag;
    694 	if (x == 1)
    695 		iflist[ifx] = !true;
    696 	if (true) {
    697 i2:
    698 		while ((cbits(i = getch())) == ' ')
    699 			;
    700 		if (cbits(i) == LEFT)
    701 			goto i2;
    702 		ch = i;
    703 		nflush++;
    704 	} else {
    705 		if (!nlflg) {
    706 			copyf++;
    707 			falsef++;
    708 			eatblk(0);
    709 			copyf--;
    710 			falsef--;
    711 		}
    712 	}
    713 }
    714 
    715 void eatblk(int inblk)
    716 {
    717 	int cnt, i;
    718 
    719 	cnt = 0;
    720 	do {
    721 		if (ch)	{
    722 			i = cbits(ch);
    723 			ch = 0;
    724 		} else
    725 			i = cbits(getch0());
    726 		if (i == ESC)
    727 			cnt++;
    728 		else {
    729 			if (cnt == 1)
    730 				switch (i) {
    731 				case '{':  i = LEFT; break;
    732 				case '}':  i = RIGHT; break;
    733 				case '\n': i = 'x'; break;
    734 				}
    735 			cnt = 0;
    736 		}
    737 		if (i == LEFT) eatblk(1);
    738 	} while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
    739 	if (i == '\n') {
    740 		nlflg++;
    741 		if (ip == 0)
    742 			numtabp[CD].val++;
    743 	}
    744 }
    745 
    746 int
    747 cmpstr(Tchar c)
    748 {
    749 	int j, delim;
    750 	Tchar i;
    751 	int val;
    752 	int savapts, savapts1, savfont, savfont1, savpts, savpts1;
    753 	Tchar string[1280];
    754 	Tchar *sp;
    755 
    756 	if (ismot(c))
    757 		return(0);
    758 	delim = cbits(c);
    759 	savapts = apts;
    760 	savapts1 = apts1;
    761 	savfont = font;
    762 	savfont1 = font1;
    763 	savpts = pts;
    764 	savpts1 = pts1;
    765 	sp = string;
    766 	while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
    767 		*sp++ = i;
    768 	if (sp >= string + 1280) {
    769 		ERROR "too-long string compare." WARN;
    770 		edone(0100);
    771 	}
    772 	if (nlflg) {
    773 		val = sp==string;
    774 		goto rtn;
    775 	}
    776 	*sp = 0;
    777 	apts = savapts;
    778 	apts1 = savapts1;
    779 	font = savfont;
    780 	font1 = savfont1;
    781 	pts = savpts;
    782 	pts1 = savpts1;
    783 	mchbits();
    784 	val = 1;
    785 	sp = string;
    786 	while ((j = cbits(i = getch())) != delim && j != '\n') {
    787 		if (*sp != i) {
    788 			eat(delim);
    789 			val = 0;
    790 			goto rtn;
    791 		}
    792 		sp++;
    793 	}
    794 	if (*sp)
    795 		val = 0;
    796 rtn:
    797 	apts = savapts;
    798 	apts1 = savapts1;
    799 	font = savfont;
    800 	font1 = savfont1;
    801 	pts = savpts;
    802 	pts1 = savpts1;
    803 	mchbits();
    804 	return(val);
    805 }
    806 
    807 
    808 void caserd(void)
    809 {
    810 
    811 	lgf++;
    812 	skip();
    813 	getname();
    814 	if (!iflg) {
    815 		if (quiet) {
    816 			if (NROFF) {
    817 				echo_off();
    818 				flusho();
    819 			}
    820 			fprintf(stderr, "\007"); /*bell*/
    821 		} else {
    822 			if (nextf[0]) {
    823 				fprintf(stderr, "%s:", nextf);
    824 			} else {
    825 				fprintf(stderr, "\007"); /*bell*/
    826 			}
    827 		}
    828 	}
    829 	collect();
    830 	tty++;
    831 	pushi(RD_OFFSET, PAIR('r','d'));
    832 }
    833 
    834 int
    835 rdtty(void)
    836 {
    837 	char	onechar;
    838 
    839 	onechar = 0;
    840 	if (read(0, &onechar, 1) == 1) {
    841 		if (onechar == '\n')
    842 			tty++;
    843 		else 
    844 			tty = 1;
    845 		if (tty != 3)
    846 			return(onechar);
    847 	}
    848 	tty = 0;
    849 	if (NROFF && quiet)
    850 		echo_on();
    851 	return(0);
    852 }
    853 
    854 
    855 void caseec(void)
    856 {
    857 	eschar = chget('\\');
    858 }
    859 
    860 
    861 void caseeo(void)
    862 {
    863 	eschar = 0;
    864 }
    865 
    866 
    867 void caseta(void)
    868 {
    869 	int i, j, k;
    870 
    871 	tabtab[0] = nonumb = 0;
    872 	for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
    873 		if (skip())
    874 			break;
    875 		k = tabtab[max(i-1, 0)] & TABMASK;
    876 		if ((j = max(hnumb(&k), 0)) > TABMASK) {
    877 			ERROR "Tab too far away" WARN;
    878 			j = TABMASK;
    879 		}
    880 		tabtab[i] = j & TABMASK;
    881 		if (!nonumb) 
    882 			switch (cbits(ch)) {
    883 			case 'C':
    884 				tabtab[i] |= CTAB;
    885 				break;
    886 			case 'R':
    887 				tabtab[i] |= RTAB;
    888 				break;
    889 			default: /*includes L*/
    890 				break;
    891 			}
    892 		nonumb = ch = 0;
    893 	}
    894 	if (!skip())
    895 		ERROR "Too many tab stops" WARN;
    896 	tabtab[i] = 0;
    897 }
    898 
    899 
    900 void casene(void)
    901 {
    902 	int i, j;
    903 
    904 	skip();
    905 	i = vnumb((int *)0);
    906 	if (nonumb)
    907 		i = lss;
    908 	if (dip == d && numtabp[NL].val == -1) {
    909 		newline(1);
    910 		return;
    911 	}
    912 	if (i > (j = findt1())) {
    913 		i = lss;
    914 		lss = j;
    915 		dip->nls = 0;
    916 		newline(0);
    917 		lss = i;
    918 	}
    919 }
    920 
    921 
    922 void casetr(void)
    923 {
    924 	int i, j;
    925 	Tchar k;
    926 
    927 	lgf++;
    928 	skip();
    929 	while ((i = cbits(k=getch())) != '\n') {
    930 		if (ismot(k))
    931 			return;
    932 		if (ismot(k = getch()))
    933 			return;
    934 		if ((j = cbits(k)) == '\n')
    935 			j = ' ';
    936 		trtab[i] = j;
    937 	}
    938 }
    939 
    940 
    941 void casecu(void)
    942 {
    943 	cu++;
    944 	caseul();
    945 }
    946 
    947 
    948 void caseul(void)
    949 {
    950 	int i;
    951 
    952 	noscale++;
    953 	skip();
    954 	i = max(atoi0(), 0);
    955 	if (nonumb)
    956 		i = 1;
    957 	if (ul && (i == 0)) {
    958 		font = sfont;
    959 		ul = cu = 0;
    960 	}
    961 	if (i) {
    962 		if (!ul) {
    963 			sfont = font;
    964 			font = ulfont;
    965 		}
    966 		ul = i;
    967 	}
    968 	noscale = 0;
    969 	mchbits();
    970 }
    971 
    972 
    973 void caseuf(void)
    974 {
    975 	int i, j;
    976 
    977 	if (skip() || !(i = getrq()) || i == 'S' ||  (j = findft(i))  == -1)
    978 		ulfont = ULFONT; /*default underline position*/
    979 	else 
    980 		ulfont = j;
    981 	if (NROFF && ulfont == FT)
    982 		ulfont = ULFONT;
    983 }
    984 
    985 
    986 void caseit(void)
    987 {
    988 	int i;
    989 
    990 	lgf++;
    991 	it = itmac = 0;
    992 	noscale++;
    993 	skip();
    994 	i = atoi0();
    995 	skip();
    996 	if (!nonumb && (itmac = getrq()))
    997 		it = i;
    998 	noscale = 0;
    999 }
   1000 
   1001 
   1002 void casemc(void)
   1003 {
   1004 	int i;
   1005 
   1006 	if (icf > 1)
   1007 		ic = 0;
   1008 	icf = 0;
   1009 	if (skip())
   1010 		return;
   1011 	ic = getch();
   1012 	icf = 1;
   1013 	skip();
   1014 	i = max(hnumb((int *)0), 0);
   1015 	if (!nonumb)
   1016 		ics = i;
   1017 }
   1018 
   1019 
   1020 void casemk(void)
   1021 {
   1022 	int i, j;
   1023 
   1024 	if (dip != d)
   1025 		j = dip->dnl; 
   1026 	else 
   1027 		j = numtabp[NL].val;
   1028 	if (skip()) {
   1029 		dip->mkline = j;
   1030 		return;
   1031 	}
   1032 	if ((i = getrq()) == 0)
   1033 		return;
   1034 	numtabp[findr(i)].val = j;
   1035 }
   1036 
   1037 
   1038 void casesv(void)
   1039 {
   1040 	int i;
   1041 
   1042 	skip();
   1043 	if ((i = vnumb((int *)0)) < 0)
   1044 		return;
   1045 	if (nonumb)
   1046 		i = 1;
   1047 	sv += i;
   1048 	caseos();
   1049 }
   1050 
   1051 
   1052 void caseos(void)
   1053 {
   1054 	int savlss;
   1055 
   1056 	if (sv <= findt1()) {
   1057 		savlss = lss;
   1058 		lss = sv;
   1059 		newline(0);
   1060 		lss = savlss;
   1061 		sv = 0;
   1062 	}
   1063 }
   1064 
   1065 
   1066 void casenm(void)
   1067 {
   1068 	int i;
   1069 
   1070 	lnmod = nn = 0;
   1071 	if (skip())
   1072 		return;
   1073 	lnmod++;
   1074 	noscale++;
   1075 	i = inumb(&numtabp[LN].val);
   1076 	if (!nonumb)
   1077 		numtabp[LN].val = max(i, 0);
   1078 	getnm(&ndf, 1);
   1079 	getnm(&nms, 0);
   1080 	getnm(&ni, 0);
   1081 	getnm(&nmwid, 3);	/* really kludgy! */
   1082 	noscale = 0;
   1083 	nmbits = chbits;
   1084 }
   1085 
   1086 /*
   1087  * .nm relies on the fact that illegal args are skipped; don't warn
   1088  * for illegality of these
   1089  */
   1090 void getnm(int *p, int min)
   1091 {
   1092 	int i;
   1093 	int savtr = trace;
   1094 
   1095 	eat(' ');
   1096 	if (skip())
   1097 		return;
   1098 	trace = 0;
   1099 	i = atoi0();
   1100 	if (nonumb)
   1101 		return;
   1102 	*p = max(i, min);
   1103 	trace = savtr;
   1104 }
   1105 
   1106 
   1107 void casenn(void)
   1108 {
   1109 	noscale++;
   1110 	skip();
   1111 	nn = max(atoi0(), 1);
   1112 	noscale = 0;
   1113 }
   1114 
   1115 
   1116 void caseab(void)
   1117 {
   1118 	casetm1(1, stderr);
   1119 	done3(0);
   1120 }
   1121 
   1122 
   1123 /* nroff terminal handling has been pretty well excised */
   1124 /* as part of the merge with troff.  these are ghostly remnants, */
   1125 /* called, but doing nothing. restore them at your peril. */
   1126 
   1127 
   1128 void save_tty(void)			/*save any tty settings that may be changed*/
   1129 {
   1130 }
   1131 
   1132 
   1133 void restore_tty(void)			/*restore tty settings from beginning*/
   1134 {
   1135 }
   1136 
   1137 
   1138 void set_tty(void)
   1139 {
   1140 }
   1141 
   1142 
   1143 void echo_off(void)			/*turn off ECHO for .rd in "-q" mode*/
   1144 {
   1145 }
   1146 
   1147 
   1148 void echo_on(void)			/*restore ECHO after .rd in "-q" mode*/
   1149 {
   1150 }