plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

n7.c (12558B)


      1 #define _BSD_SOURCE 1	/* isascii */
      2 #define _DEFAULT_SOURCE 1
      3 #include "tdef.h"
      4 #include "fns.h"
      5 #include "ext.h"
      6 
      7 #ifdef STRICT
      8 	/* not in ANSI or POSIX */
      9 #define	isascii(a) ((a) >= 0 && (a) <= 127)
     10 #endif
     11 
     12 #define GETCH gettch
     13 Tchar	gettch(void);
     14 
     15 
     16 /*
     17  * troff7.c
     18  *
     19  * text
     20  */
     21 
     22 int	brflg;
     23 
     24 void tbreak(void)
     25 {
     26 	int pad, k;
     27 	Tchar *i, j;
     28 	int resol;
     29 	int un0 = un;
     30 
     31 	trap = 0;
     32 	if (nb)
     33 		return;
     34 	if (dip == d && numtabp[NL].val == -1) {
     35 		newline(1);
     36 		return;
     37 	}
     38 	if (!nc) {
     39 		setnel();
     40 		if (!wch)
     41 			return;
     42 		if (pendw)
     43 			getword(1);
     44 		movword();
     45 	} else if (pendw && !brflg) {
     46 		getword(1);
     47 		movword();
     48 	}
     49 	*linep = dip->nls = 0;
     50 	if (NROFF && dip == d)
     51 		horiz(po);
     52 	if (lnmod)
     53 		donum();
     54 	lastl = ne;
     55 	if (brflg != 1) {
     56 		totout = 0;
     57 	} else if (ad) {
     58 		if ((lastl = ll - un) < ne)
     59 			lastl = ne;
     60 	}
     61 	if (admod && ad && (brflg != 2)) {
     62 		lastl = ne;
     63 		adsp = adrem = 0;
     64 		if (admod == 1)
     65 			un +=  quant(nel / 2, HOR);
     66 		else if (admod == 2)
     67 			un += nel;
     68 	}
     69 	totout++;
     70 	brflg = 0;
     71 	if (lastl + un > dip->maxl)
     72 		dip->maxl = lastl + un;
     73 	horiz(un);
     74 	if (NROFF) {
     75 		if (adrem % t.Adj)
     76 			resol = t.Hor;
     77 		else
     78 			resol = t.Adj;
     79 	} else
     80 		resol = HOR;
     81 
     82 	lastl = ne + (nwd-1) * adsp + adrem;
     83 	for (i = line; nc > 0; ) {
     84 		if ((cbits(j = *i++)) == ' ') {
     85 			pad = 0;
     86 			do {
     87 				pad += width(j);
     88 				nc--;
     89 			} while ((cbits(j = *i++)) == ' ');
     90 			i--;
     91 			pad += adsp;
     92 			--nwd;
     93 			if (adrem) {
     94 				if (adrem < 0) {
     95 					pad -= resol;
     96 					adrem += resol;
     97 				} else if ((totout & 01) || adrem / resol >= nwd) {
     98 					pad += resol;
     99 					adrem -= resol;
    100 				}
    101 			}
    102 			pchar((Tchar) WORDSP);
    103 			horiz(pad);
    104 		} else {
    105 			pchar(j);
    106 			nc--;
    107 		}
    108 	}
    109 	if (ic) {
    110 		if ((k = ll - un0 - lastl + ics) > 0)
    111 			horiz(k);
    112 		pchar(ic);
    113 	}
    114 	if (icf)
    115 		icf++;
    116 	else
    117 		ic = 0;
    118 	ne = nwd = 0;
    119 	un = in;
    120 	setnel();
    121 	newline(0);
    122 	if (dip != d) {
    123 		if (dip->dnl > dip->hnl)
    124 			dip->hnl = dip->dnl;
    125 	} else {
    126 		if (numtabp[NL].val > dip->hnl)
    127 			dip->hnl = numtabp[NL].val;
    128 	}
    129 	for (k = ls - 1; k > 0 && !trap; k--)
    130 		newline(0);
    131 	spread = 0;
    132 }
    133 
    134 void donum(void)
    135 {
    136 	int i, nw;
    137 	int lnv = numtabp[LN].val;
    138 
    139 	nrbits = nmbits;
    140 	nw = width('1' | nrbits);
    141 	if (nn) {
    142 		nn--;
    143 		goto d1;
    144 	}
    145 	if (lnv % ndf) {
    146 		numtabp[LN].val++;
    147 d1:
    148 		un += nw * (nmwid + nms + ni);
    149 		return;
    150 	}
    151 	i = 0;
    152 	do {		/* count digits in numtabp[LN].val */
    153 		i++;
    154 	} while ((lnv /= 10) > 0);
    155 	horiz(nw * (ni + max(nmwid-i, 0)));
    156 	nform = 0;
    157 	fnumb(numtabp[LN].val, pchar);
    158 	un += nw * nms;
    159 	numtabp[LN].val++;
    160 }
    161 
    162 
    163 void text(void)
    164 {
    165 	Tchar i;
    166 	static int spcnt;
    167 
    168 	nflush++;
    169 	numtabp[HP].val = 0;
    170 	if ((dip == d) && (numtabp[NL].val == -1)) {
    171 		newline(1);
    172 		return;
    173 	}
    174 	setnel();
    175 	if (ce || !fi) {
    176 		nofill();
    177 		return;
    178 	}
    179 	if (pendw)
    180 		goto t4;
    181 	if (pendt)
    182 		if (spcnt)
    183 			goto t2;
    184 		else
    185 			goto t3;
    186 	pendt++;
    187 	if (spcnt)
    188 		goto t2;
    189 	while ((cbits(i = GETCH())) == ' ') {
    190 		spcnt++;
    191 		numtabp[HP].val += sps;
    192 		widthp = sps;
    193 	}
    194 	if (nlflg) {
    195 t1:
    196 		nflush = pendt = ch = spcnt = 0;
    197 		callsp();
    198 		return;
    199 	}
    200 	ch = i;
    201 	if (spcnt) {
    202 t2:
    203 		tbreak();
    204 		if (nc || wch)
    205 			goto rtn;
    206 		un += spcnt * sps;
    207 		spcnt = 0;
    208 		setnel();
    209 		if (trap)
    210 			goto rtn;
    211 		if (nlflg)
    212 			goto t1;
    213 	}
    214 t3:
    215 	if (spread)
    216 		goto t5;
    217 	if (pendw || !wch)
    218 t4:
    219 		if (getword(0))
    220 			goto t6;
    221 	if (!movword())
    222 		goto t3;
    223 t5:
    224 	if (nlflg)
    225 		pendt = 0;
    226 	adsp = adrem = 0;
    227 	if (ad) {
    228 		if (nwd == 1)
    229 			adsp = nel;
    230 		else
    231 			adsp = nel / (nwd - 1);
    232 		adsp = (adsp / HOR) * HOR;
    233 		adrem = nel - adsp*(nwd-1);
    234 	}
    235 	brflg = 1;
    236 	tbreak();
    237 	spread = 0;
    238 	if (!trap)
    239 		goto t3;
    240 	if (!nlflg)
    241 		goto rtn;
    242 t6:
    243 	pendt = 0;
    244 	ckul();
    245 rtn:
    246 	nflush = 0;
    247 }
    248 
    249 
    250 void nofill(void)
    251 {
    252 	int j;
    253 	Tchar i;
    254 
    255 	if (!pendnf) {
    256 		over = 0;
    257 		tbreak();
    258 		if (trap)
    259 			goto rtn;
    260 		if (nlflg) {
    261 			ch = nflush = 0;
    262 			callsp();
    263 			return;
    264 		}
    265 		adsp = adrem = 0;
    266 		nwd = 10000;
    267 	}
    268 	while ((j = (cbits(i = GETCH()))) != '\n') {
    269 		if (j == ohc)
    270 			continue;
    271 		if (j == CONT) {
    272 			pendnf++;
    273 			nflush = 0;
    274 			flushi();
    275 			ckul();
    276 			return;
    277 		}
    278 		j = width(i);
    279 		widthp = j;
    280 		numtabp[HP].val += j;
    281 		storeline(i, j);
    282 	}
    283 	if (ce) {
    284 		ce--;
    285 		if ((i = quant(nel / 2, HOR)) > 0)
    286 			un += i;
    287 	}
    288 	if (!nc)
    289 		storeline((Tchar)FILLER, 0);
    290 	brflg = 2;
    291 	tbreak();
    292 	ckul();
    293 rtn:
    294 	pendnf = nflush = 0;
    295 }
    296 
    297 
    298 void callsp(void)
    299 {
    300 	int i;
    301 
    302 	if (flss)
    303 		i = flss;
    304 	else
    305 		i = lss;
    306 	flss = 0;
    307 	casesp1(i);
    308 }
    309 
    310 
    311 void ckul(void)
    312 {
    313 	if (ul && (--ul == 0)) {
    314 		cu = 0;
    315 		font = sfont;
    316 		mchbits();
    317 	}
    318 	if (it && --it == 0 && itmac)
    319 		control(itmac, 0);
    320 }
    321 
    322 
    323 void storeline(Tchar c, int w)
    324 {
    325 	int diff;
    326 
    327 	if (linep >= line + lnsize - 2) {
    328 		lnsize += LNSIZE;
    329 		diff = linep - line;
    330 		if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) {
    331 			if (linep && diff)
    332 				linep = line + diff;
    333 		} else {
    334 			if (over) {
    335 				return;
    336 			} else {
    337 				flusho();
    338 				ERROR "Line overflow." WARN;
    339 				over++;
    340 				*linep++ = LEFTHAND;
    341 				w = width(LEFTHAND);
    342 				nc++;
    343 				c = '\n';
    344 			}
    345 		}
    346 	}
    347 	*linep++ = c;
    348 	ne += w;
    349 	nel -= w;
    350 	nc++;
    351 }
    352 
    353 
    354 void newline(int a)
    355 {
    356 	int i, j, nlss;
    357 	int opn;
    358 
    359 	nlss = 0;
    360 	if (a)
    361 		goto nl1;
    362 	if (dip != d) {
    363 		j = lss;
    364 		pchar1((Tchar)FLSS);
    365 		if (flss)
    366 			lss = flss;
    367 		i = lss + dip->blss;
    368 		dip->dnl += i;
    369 		pchar1((Tchar)i);
    370 		pchar1((Tchar)'\n');
    371 		lss = j;
    372 		dip->blss = flss = 0;
    373 		if (dip->alss) {
    374 			pchar1((Tchar)FLSS);
    375 			pchar1((Tchar)dip->alss);
    376 			pchar1((Tchar)'\n');
    377 			dip->dnl += dip->alss;
    378 			dip->alss = 0;
    379 		}
    380 		if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)
    381 			if (control(dip->dimac, 0)) {
    382 				trap++;
    383 				dip->ditf++;
    384 			}
    385 		return;
    386 	}
    387 	j = lss;
    388 	if (flss)
    389 		lss = flss;
    390 	nlss = dip->alss + dip->blss + lss;
    391 	numtabp[NL].val += nlss;
    392 	if (TROFF && ascii) {
    393 		dip->alss = dip->blss = 0;
    394 	}
    395 	pchar1((Tchar)'\n');
    396 	flss = 0;
    397 	lss = j;
    398 	if (numtabp[NL].val < pl)
    399 		goto nl2;
    400 nl1:
    401 	ejf = dip->hnl = numtabp[NL].val = 0;
    402 	ejl = frame;
    403 	if (donef) {
    404 		if ((!nc && !wch) || ndone)
    405 			done1(0);
    406 		ndone++;
    407 		donef = 0;
    408 		if (frame == stk)
    409 			nflush++;
    410 	}
    411 	opn = numtabp[PN].val;
    412 	numtabp[PN].val++;
    413 	if (npnflg) {
    414 		numtabp[PN].val = npn;
    415 		npn = npnflg = 0;
    416 	}
    417 nlpn:
    418 	if (numtabp[PN].val == pfrom) {
    419 		print++;
    420 		pfrom = -1;
    421 	} else if (opn == pto) {
    422 		print = 0;
    423 		opn = -1;
    424 		chkpn();
    425 		goto nlpn;
    426 	}
    427 	if (print)
    428 		ptpage(numtabp[PN].val);	/* supposedly in a clean state so can pause */
    429 	if (stop && print) {
    430 		dpn++;
    431 		if (dpn >= stop) {
    432 			dpn = 0;
    433 			ptpause();
    434 		}
    435 	}
    436 nl2:
    437 	trap = 0;
    438 	if (numtabp[NL].val == 0) {
    439 		if ((j = findn(0)) != NTRAP)
    440 			trap = control(mlist[j], 0);
    441 	} else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) {
    442 		if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) {
    443 			flusho();
    444 			ERROR "Trap botch." WARN;
    445 			done2(-5);
    446 		}
    447 		trap = control(mlist[j], 0);
    448 	}
    449 }
    450 
    451 int
    452 findn1(int a)
    453 {
    454 	int i, j;
    455 
    456 	for (i = 0; i < NTRAP; i++) {
    457 		if (mlist[i]) {
    458 			if ((j = nlist[i]) < 0)
    459 				j += pl;
    460 			if (j == a)
    461 				break;
    462 		}
    463 	}
    464 	return(i);
    465 }
    466 
    467 
    468 void chkpn(void)
    469 {
    470 	pto = *(pnp++);
    471 	pfrom = pto>=0 ? pto : -pto;
    472 	if (pto == -INT_MAX) {
    473 		flusho();
    474 		done1(0);
    475 	}
    476 	if (pto < 0) {
    477 		pto = -pto;
    478 		print++;
    479 		pfrom = 0;
    480 	}
    481 }
    482 
    483 int
    484 findt(int a)
    485 {
    486 	int i, j, k;
    487 
    488 	k = INT_MAX;
    489 	if (dip != d) {
    490 		if (dip->dimac && (i = dip->ditrap - a) > 0)
    491 			k = i;
    492 		return(k);
    493 	}
    494 	for (i = 0; i < NTRAP; i++) {
    495 		if (mlist[i]) {
    496 			if ((j = nlist[i]) < 0)
    497 				j += pl;
    498 			if ((j -= a) <= 0)
    499 				continue;
    500 			if (j < k)
    501 				k = j;
    502 		}
    503 	}
    504 	i = pl - a;
    505 	if (k > i)
    506 		k = i;
    507 	return(k);
    508 }
    509 
    510 int
    511 findt1(void)
    512 {
    513 	int i;
    514 
    515 	if (dip != d)
    516 		i = dip->dnl;
    517 	else
    518 		i = numtabp[NL].val;
    519 	return(findt(i));
    520 }
    521 
    522 
    523 void eject(Stack *a)
    524 {
    525 	int savlss;
    526 
    527 	if (dip != d)
    528 		return;
    529 	ejf++;
    530 	if (a)
    531 		ejl = a;
    532 	else
    533 		ejl = frame;
    534 	if (trap)
    535 		return;
    536 e1:
    537 	savlss = lss;
    538 	lss = findt(numtabp[NL].val);
    539 	newline(0);
    540 	lss = savlss;
    541 	if (numtabp[NL].val && !trap)
    542 		goto e1;
    543 }
    544 
    545 int
    546 movword(void)
    547 {
    548 	int w;
    549 	Tchar i, *wp;
    550 	int savwch, hys;
    551 
    552 	over = 0;
    553 	wp = wordp;
    554 	if (!nwd) {
    555 		while (cbits(*wp++) == ' ') {
    556 			wch--;
    557 			wne -= sps;
    558 		}
    559 		wp--;
    560 	}
    561 	if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) &&
    562 	   (!(hyf & 02) || (findt1() > lss)))
    563 		hyphen(wp);
    564 	savwch = wch;
    565 	hyp = hyptr;
    566 	nhyp = 0;
    567 	while (*hyp && *hyp <= wp)
    568 		hyp++;
    569 	while (wch) {
    570 		if (hyoff != 1 && *hyp == wp) {
    571 			hyp++;
    572 			if (!wdstart || (wp > wdstart + 1 && wp < wdend &&
    573 			   (!(hyf & 04) || wp < wdend - 1) &&		/* 04 => last 2 */
    574 			   (!(hyf & 010) || wp > wdstart + 2))) {	/* 010 => 1st 2 */
    575 				nhyp++;
    576 				storeline((Tchar)IMP, 0);
    577 			}
    578 		}
    579 		i = *wp++;
    580 		w = width(i);
    581 		wne -= w;
    582 		wch--;
    583 		storeline(i, w);
    584 	}
    585 	if (nel >= 0) {
    586 		nwd++;
    587 		return(0);	/* line didn't fill up */
    588 	}
    589 	if (TROFF)
    590 		xbits((Tchar)HYPHEN, 1);
    591 	hys = width((Tchar)HYPHEN);
    592 m1:
    593 	if (!nhyp) {
    594 		if (!nwd)
    595 			goto m3;
    596 		if (wch == savwch)
    597 			goto m4;
    598 	}
    599 	if (*--linep != IMP)
    600 		goto m5;
    601 	if (!(--nhyp))
    602 		if (!nwd)
    603 			goto m2;
    604 	if (nel < hys) {
    605 		nc--;
    606 		goto m1;
    607 	}
    608 m2:
    609 	if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) {
    610 		*linep = (*(linep - 1) & SFMASK) | HYPHEN;
    611 		w = width(*linep);
    612 		nel -= w;
    613 		ne += w;
    614 		linep++;
    615 	}
    616 m3:
    617 	nwd++;
    618 m4:
    619 	wordp = wp;
    620 	return(1);	/* line filled up */
    621 m5:
    622 	nc--;
    623 	w = width(*linep);
    624 	ne -= w;
    625 	nel += w;
    626 	wne += w;
    627 	wch++;
    628 	wp--;
    629 	goto m1;
    630 }
    631 
    632 
    633 void horiz(int i)
    634 {
    635 	vflag = 0;
    636 	if (i)
    637 		pchar(makem(i));
    638 }
    639 
    640 
    641 void setnel(void)
    642 {
    643 	if (!nc) {
    644 		linep = line;
    645 		if (un1 >= 0) {
    646 			un = un1;
    647 			un1 = -1;
    648 		}
    649 		nel = ll - un;
    650 		ne = adsp = adrem = 0;
    651 	}
    652 }
    653 
    654 int
    655 getword(int x)
    656 {
    657 	int j, k;
    658 	Tchar i, *wp;
    659 	int noword;
    660 	int obits;
    661 
    662 	j = 0;
    663 	noword = 0;
    664 	if (x)
    665 		if (pendw) {
    666 			*pendw = 0;
    667 			goto rtn;
    668 		}
    669 	if (wordp = pendw)
    670 		goto g1;
    671 	hyp = hyptr;
    672 	wordp = word;
    673 	over = wne = wch = 0;
    674 	hyoff = 0;
    675 	obits = chbits;
    676 	while (1) {	/* picks up 1st char of word */
    677 		j = cbits(i = GETCH());
    678 		if (j == '\n') {
    679 			wne = wch = 0;
    680 			noword = 1;
    681 			goto rtn;
    682 		}
    683 		if (j == ohc) {
    684 			hyoff = 1;	/* 1 => don't hyphenate */
    685 			continue;
    686 		}
    687 		if (j == ' ') {
    688 			numtabp[HP].val += sps;
    689 			widthp = sps;
    690 			storeword(i, sps);
    691 			continue;
    692 		}
    693 		break;
    694 	}
    695 	storeword(' ' | obits, sps);
    696 	if (spflg) {
    697 		storeword(' ' | obits, sps);
    698 		spflg = 0;
    699 	}
    700 g0:
    701 	if (j == CONT) {
    702 		pendw = wordp;
    703 		nflush = 0;
    704 		flushi();
    705 		return(1);
    706 	}
    707 	if (hyoff != 1) {
    708 		if (j == ohc) {
    709 			hyoff = 2;
    710 			*hyp++ = wordp;
    711 			if (hyp > hyptr + NHYP - 1)
    712 				hyp = hyptr + NHYP - 1;
    713 			goto g1;
    714 		}
    715 		if (((j == '-' || j == EMDASH)) && !(i & ZBIT))	/* zbit avoids \X */
    716 			if (wordp > word + 1) {
    717 				hyoff = 2;
    718 				*hyp++ = wordp + 1;
    719 				if (hyp > hyptr + NHYP - 1)
    720 					hyp = hyptr + NHYP - 1;
    721 			}
    722 	}
    723 	j = width(i);
    724 	numtabp[HP].val += j;
    725 	storeword(i, j);
    726 g1:
    727 	j = cbits(i = GETCH());
    728 	if (j != ' ') {
    729 		static char *sentchar = ".?!";	/* sentence terminators */
    730 		if (j != '\n')
    731 			goto g0;
    732 		wp = wordp-1;	/* handle extra space at end of sentence */
    733 		while (wp >= word) {
    734 			j = cbits(*wp--);
    735 			if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER)
    736 				continue;
    737 			for (k = 0; sentchar[k]; k++)
    738 				if (j == sentchar[k]) {
    739 					spflg++;
    740 					break;
    741 				}
    742 			break;
    743 		}
    744 	}
    745 	*wordp = 0;
    746 	numtabp[HP].val += sps;
    747 rtn:
    748 	for (wp = word; *wp; wp++) {
    749 		if (ismot(j))
    750 			break;	/* drechsler */
    751 		j = cbits(*wp);
    752 		if (j == ' ')
    753 			continue;
    754 		if (!(isascii(j) && isdigit(j)) && j != '-')
    755 			break;
    756 	}
    757 	if (*wp == 0)	/* all numbers, so don't hyphenate */
    758 		hyoff = 1;
    759 	wdstart = 0;
    760 	wordp = word;
    761 	pendw = 0;
    762 	*hyp++ = 0;
    763 	setnel();
    764 	return(noword);
    765 }
    766 
    767 
    768 void storeword(Tchar c, int w)
    769 {
    770 	Tchar *savp;
    771 	int i;
    772 
    773 	if (wordp >= word + wdsize - 2) {
    774 		wdsize += WDSIZE;
    775 		savp = word;
    776 		if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) {
    777 			if (wordp)
    778 				wordp = word + (wordp - savp);
    779 			if (pendw)
    780 				pendw = word + (pendw - savp);
    781 			if (wdstart)
    782 				wdstart = word + (wdstart - savp);
    783 			if (wdend)
    784 				wdend = word + (wdend - savp);
    785 			for (i = 0; i < NHYP; i++)
    786 				if (hyptr[i])
    787 					hyptr[i] = word + (hyptr[i] - savp);
    788 		} else {
    789 			if (over) {
    790 				return;
    791 			} else {
    792 				flusho();
    793 				ERROR "Word overflow." WARN;
    794 				over++;
    795 				c = LEFTHAND;
    796 				w = width(LEFTHAND);
    797 			}
    798 		}
    799 	}
    800 	widthp = w;
    801 	wne += w;
    802 	*wordp++ = c;
    803 	wch++;
    804 }
    805 
    806 
    807 Tchar gettch(void)
    808 {
    809 	extern int c_isalnum;
    810 	Tchar i;
    811 	int j;
    812 
    813 	if (TROFF)
    814 		return getch();
    815 
    816 	i = getch();
    817 	j = cbits(i);
    818 	if (ismot(i) || fbits(i) != ulfont)
    819 		return(i);
    820 	if (cu) {
    821 		if (trtab[j] == ' ') {
    822 			setcbits(i, '_');
    823 			setfbits(i, FT);	/* default */
    824 		}
    825 		return(i);
    826 	}
    827 	/* should test here for characters that ought to be underlined */
    828 	/* in the old nroff, that was the 200 bit on the width! */
    829 	/* for now, just do letters, digits and certain special chars */
    830 	if (j <= 127) {
    831 		if (!isalnum(j))
    832 			setfbits(i, FT);
    833 	} else {
    834 		if (j < c_isalnum)
    835 			setfbits(i, FT);
    836 	}
    837 	return(i);
    838 }