9base

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

n7.c (12546B)


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