9base

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

n9.c (9091B)


      1 #include "tdef.h"
      2 #include "ext.h"
      3 #include "fns.h"
      4 
      5 /*
      6  * troff9.c
      7  * 
      8  * misc functions
      9  */
     10 
     11 Tchar setz(void)
     12 {
     13 	Tchar i;
     14 
     15 	if (!ismot(i = getch()))
     16 		i |= ZBIT;
     17 	return(i);
     18 }
     19 
     20 void setline(void)
     21 {
     22 	Tchar *i;
     23 	Tchar c;
     24 	int length;
     25 	int j, w, cnt, delim, rem, temp;
     26 	Tchar linebuf[NC];
     27 
     28 	if (ismot(c = getch()))
     29 		return;
     30 	delim = cbits(c);
     31 	vflag = 0;
     32 	dfact = EM;
     33 	length = quant(atoi0(), HOR);
     34 	dfact = 1;
     35 	if (!length) {
     36 		eat(delim);
     37 		return;
     38 	}
     39 s0:
     40 	if ((j = cbits(c = getch())) == delim || j == '\n') {
     41 		ch = c;
     42 		c = RULE | chbits;
     43 	} else if (cbits(c) == FILLER)
     44 		goto s0;
     45 	w = width(c);
     46 	if (w <= 0) {
     47 		ERROR "zero-width underline character ignored" WARN;
     48 		c = RULE | chbits;
     49 		w = width(c);
     50 	}
     51 	i = linebuf;
     52 	if (length < 0) {
     53 		*i++ = makem(length);
     54 		length = -length;
     55 	}
     56 	if (!(cnt = length / w)) {
     57 		*i++ = makem(-(temp = ((w - length) / 2)));
     58 		*i++ = c;
     59 		*i++ = makem(-(w - length - temp));
     60 		goto s1;
     61 	}
     62 	if (rem = length % w) {
     63 		if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN)
     64 			*i++ = c | ZBIT;
     65 		*i++ = makem(rem);
     66 	}
     67 	if (cnt) {
     68 		*i++ = RPT;
     69 		*i++ = cnt;
     70 		*i++ = c;
     71 	}
     72 s1:
     73 	*i = 0;
     74 	eat(delim);
     75 	pushback(linebuf);
     76 }
     77 
     78 int
     79 eat(int c)
     80 {
     81 	int i;
     82 
     83 	while ((i = cbits(getch())) != c && i != '\n')
     84 		;
     85 	return(i);
     86 }
     87 
     88 
     89 void setov(void)
     90 {
     91 	int j, k;
     92 	Tchar i, o[NOV+1];
     93 	int delim, w[NOV+1];
     94 
     95 	if (ismot(i = getch()))
     96 		return;
     97 	delim = cbits(i);
     98 	for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) {
     99 		o[k] = i;
    100 		w[k] = width(i);
    101 	}
    102 	o[k] = w[k] = 0;
    103 	if (o[0])
    104 		for (j = 1; j; ) {
    105 			j = 0;
    106 			for (k = 1; o[k] ; k++) {
    107 				if (w[k-1] < w[k]) {
    108 					j++;
    109 					i = w[k];
    110 					w[k] = w[k-1];
    111 					w[k-1] = i;
    112 					i = o[k];
    113 					o[k] = o[k-1];
    114 					o[k-1] = i;
    115 				}
    116 			}
    117 		}
    118 	else 
    119 		return;
    120 	*pbp++ = makem(w[0] / 2);
    121 	for (k = 0; o[k]; k++)
    122 		;
    123 	while (k>0) {
    124 		k--;
    125 		*pbp++ = makem(-((w[k] + w[k+1]) / 2));
    126 		*pbp++ = o[k];
    127 	}
    128 }
    129 
    130 
    131 void setbra(void)
    132 {
    133 	int k;
    134 	Tchar i, *j, dwn;
    135 	int cnt, delim;
    136 	Tchar brabuf[NC];
    137 
    138 	if (ismot(i = getch()))
    139 		return;
    140 	delim = cbits(i);
    141 	j = brabuf + 1;
    142 	cnt = 0;
    143 	if (NROFF)
    144 		dwn = (2 * t.Halfline) | MOT | VMOT;
    145 	else
    146 		dwn = EM | MOT | VMOT;
    147 	while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) {
    148 		*j++ = i | ZBIT;
    149 		*j++ = dwn;
    150 		cnt++;
    151 	}
    152 	if (--cnt < 0)
    153 		return;
    154 	else if (!cnt) {
    155 		ch = *(j - 2);
    156 		return;
    157 	}
    158 	*j = 0;
    159 	if (NROFF)
    160 		*--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT;
    161 	else
    162 		*--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT;
    163 	*--j &= ~ZBIT;
    164 	pushback(brabuf);
    165 }
    166 
    167 
    168 void setvline(void)
    169 {
    170 	int i;
    171 	Tchar c, rem, ver, neg;
    172 	int cnt, delim, v;
    173 	Tchar vlbuf[NC];
    174 	Tchar *vlp;
    175 
    176 	if (ismot(c = getch()))
    177 		return;
    178 	delim = cbits(c);
    179 	dfact = lss;
    180 	vflag++;
    181 	i = quant(atoi0(), VERT);
    182 	dfact = 1;
    183 	if (!i) {
    184 		eat(delim);
    185 		vflag = 0;
    186 		return;
    187 	}
    188 	if ((cbits(c = getch())) == delim) {
    189 		c = BOXRULE | chbits;	/*default box rule*/
    190 	} else 
    191 		getch();
    192 	c |= ZBIT;
    193 	neg = 0;
    194 	if (i < 0) {
    195 		i = -i;
    196 		neg = NMOT;
    197 	}
    198 	if (NROFF)
    199 		v = 2 * t.Halfline;
    200 	else {
    201 		v = EM;
    202 		if (v < VERT)		/* ATT EVK hack: Erik van Konijnenburg, */
    203 			v = VERT;	/* hvlpb!evkonij, ATT NSI Hilversum, Holland */
    204 	}
    205 
    206 	cnt = i / v;
    207 	rem = makem(i % v) | neg;
    208 	ver = makem(v) | neg;
    209 	vlp = vlbuf;
    210 	if (!neg)
    211 		*vlp++ = ver;
    212 	if (absmot(rem) != 0) {
    213 		*vlp++ = c;
    214 		*vlp++ = rem;
    215 	}
    216 	while (vlp < vlbuf + NC - 3 && cnt--) {
    217 		*vlp++ = c;
    218 		*vlp++ = ver;
    219 	}
    220 	*(vlp - 2) &= ~ZBIT;
    221 	if (!neg)
    222 		vlp--;
    223 	*vlp = 0;
    224 	pushback(vlbuf);
    225 	vflag = 0;
    226 }
    227 
    228 #define	NPAIR	(NC/2-6)	/* max pairs in spline, etc. */
    229 
    230 void setdraw(void)	/* generate internal cookies for a drawing function */
    231 {
    232 	int i, j, k, dx[NPAIR], dy[NPAIR], delim, type;
    233 	Tchar c, drawbuf[NC];
    234 	int drawch = '.';	/* character to draw with */
    235 
    236 	/* input is \D'f dx dy dx dy ... c' (or at least it had better be) */
    237 	/* this does drawing function f with character c and the */
    238 	/* specified dx,dy pairs interpreted as appropriate */
    239 	/* pairs are deltas from last point, except for radii */
    240 
    241 	/* l dx dy:	line from here by dx,dy */
    242 	/* c x:		circle of diameter x, left side here */
    243 	/* e x y:	ellipse of diameters x,y, left side here */
    244 	/* a dx1 dy1 dx2 dy2:
    245 			ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */
    246 	/* ~ dx1 dy1 dx2 dy2...:
    247 			spline to dx1,dy1 to dx2,dy2 ... */
    248 	/* b x c:
    249 			built-up character of type c, ht x */
    250 	/* f dx dy ...:	f is any other char:  like spline */
    251 
    252 	if (ismot(c = getch()))
    253 		return;
    254 	delim = cbits(c);
    255 	numerr.escarg = type = cbits(getch());
    256 	if (type == '~')	/* head off the .tr ~ problem */
    257 		type = 's';
    258 	for (i = 0; i < NPAIR ; i++) {
    259 		skip();
    260 		vflag = 0;
    261 		dfact = EM;
    262 		dx[i] = quant(atoi0(), HOR);
    263 		if (dx[i] > MAXMOT)
    264 			dx[i] = MAXMOT;
    265 		else if (dx[i] < -MAXMOT)
    266 			dx[i] = -MAXMOT;
    267 		skip();
    268 		if (type == 'c') {
    269 			dy[i] = 0;
    270 			goto eat;
    271 		}
    272 		vflag = 1;
    273 		dfact = lss;
    274 		dy[i] = quant(atoi0(), VERT);
    275 		if (dy[i] > MAXMOT)
    276 			dy[i] = MAXMOT;
    277 		else if (dy[i] < -MAXMOT)
    278 			dy[i] = -MAXMOT;
    279 eat:
    280 		if (cbits(c = getch()) != ' ') {	/* must be the end */
    281 			if (cbits(c) != delim) {
    282 				drawch = cbits(c);
    283 				getch();
    284 			}
    285 			i++;
    286 			break;
    287 		}
    288 	}
    289 	dfact = 1;
    290 	vflag = 0;
    291 	if (TROFF) {
    292 		drawbuf[0] = DRAWFCN | chbits | ZBIT;
    293 		drawbuf[1] = type | chbits | ZBIT;
    294 		drawbuf[2] = drawch | chbits | ZBIT;
    295 		for (k = 0, j = 3; k < i; k++) {
    296 			drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k]));
    297 			drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k]));
    298 		}
    299 		if (type == DRAWELLIPSE) {
    300 			drawbuf[5] = drawbuf[4] | NMOT;	/* so the net vertical is zero */
    301 			j = 6;
    302 		} else if (type == DRAWBUILD) {
    303 			drawbuf[4] = drawbuf[3] | NMOT;	/* net horizontal motion is zero */
    304 			drawbuf[2] &= ~ZBIT;		/* width taken from drawing char */
    305 			j = 5;
    306 		}
    307 		drawbuf[j++] = DRAWFCN | chbits | ZBIT;	/* marks end for ptout */
    308 		drawbuf[j] = 0;
    309 		pushback(drawbuf);
    310 	}
    311 }
    312 
    313 
    314 void casefc(void)
    315 {
    316 	int i;
    317 	Tchar j;
    318 
    319 	gchtab[fc] &= ~FCBIT;
    320 	fc = IMP;
    321 	padc = ' ';
    322 	if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n')
    323 		return;
    324 	fc = i;
    325 	gchtab[fc] |= FCBIT;
    326 	if (skip() || ismot(ch) || (ch = cbits(ch)) == fc)
    327 		return;
    328 	padc = ch;
    329 }
    330 
    331 
    332 Tchar setfield(int x)
    333 {
    334 	Tchar ii, jj, *fp;
    335 	int i, j;
    336 	int length, ws, npad, temp, type;
    337 	Tchar **pp, *padptr[NPP];
    338 	Tchar fbuf[FBUFSZ];
    339 	int savfc, savtc, savlc;
    340 	Tchar rchar;
    341 	int savepos;
    342 	static Tchar wbuf[] = { WORDSP, 0};
    343 
    344 	rchar = 0;
    345 	if (x == tabch) 
    346 		rchar = tabc | chbits;
    347 	else if (x ==  ldrch) 
    348 		rchar = dotc | chbits;
    349 	temp = npad = ws = 0;
    350 	savfc = fc;
    351 	savtc = tabch;
    352 	savlc = ldrch;
    353 	tabch = ldrch = fc = IMP;
    354 	savepos = numtabp[HP].val;
    355 	gchtab[tabch] &= ~TABBIT;
    356 	gchtab[ldrch] &= ~LDRBIT;
    357 	gchtab[fc] &= ~FCBIT;
    358 	gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
    359 	for (j = 0; ; j++) {
    360 		if ((tabtab[j] & TABMASK) == 0) {
    361 			if (x == savfc)
    362 				ERROR "zero field width." WARN;
    363 			jj = 0;
    364 			goto rtn;
    365 		}
    366 		if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 )
    367 			break;
    368 	}
    369 	type = tabtab[j] & ~TABMASK;
    370 	fp = fbuf;
    371 	pp = padptr;
    372 	if (x == savfc) {
    373 		while (1) {
    374 			j = cbits(ii = getch());
    375 			jj = width(ii);
    376 			widthp = jj;
    377 			numtabp[HP].val += jj;
    378 			if (j == padc) {
    379 				npad++;
    380 				*pp++ = fp;
    381 				if (pp > padptr + NPP - 1)
    382 					break;
    383 				goto s1;
    384 			} else if (j == savfc) 
    385 				break;
    386 			else if (j == '\n') {
    387 				temp = j;
    388 				if (nlflg && ip == 0) {
    389 					numtabp[CD].val--;
    390 					nlflg = 0;
    391 				}
    392 				break;
    393 			}
    394 			ws += jj;
    395 s1:
    396 			*fp++ = ii;
    397 			if (fp > fbuf + FBUFSZ - 3)
    398 				break;
    399 		}
    400 		if (ws)
    401 			*fp++ = WORDSP;
    402 		if (!npad) {
    403 			npad++;
    404 			*pp++ = fp;
    405 			*fp++ = 0;
    406 		}
    407 		*fp++ = temp;
    408 		*fp = 0;
    409 		temp = i = (j = length - ws) / npad;
    410 		i = (i / HOR) * HOR;
    411 		if ((j -= i * npad) < 0)
    412 			j = -j;
    413 		ii = makem(i);
    414 		if (temp < 0)
    415 			ii |= NMOT;
    416 		for (; npad > 0; npad--) {
    417 			*(*--pp) = ii;
    418 			if (j) {
    419 				j -= HOR;
    420 				(*(*pp)) += HOR;
    421 			}
    422 		}
    423 		pushback(fbuf);
    424 		jj = 0;
    425 	} else if (type == 0) {
    426 		/*plain tab or leader*/
    427 		if ((j = width(rchar)) > 0) {
    428 			int nchar = length / j;
    429 			while (nchar-->0 && pbp < &pbbuf[NC-3]) {
    430 				numtabp[HP].val += j;
    431 				widthp = j;
    432 				*pbp++ = rchar;
    433 			}
    434 			length %= j;
    435 		}
    436 		if (length)
    437 			jj = length | MOT;
    438 		else 
    439 			jj = getch0();
    440 		if (savepos > 0)
    441 			pushback(wbuf);
    442 	} else {
    443 		/*center tab*/
    444 		/*right tab*/
    445 		while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) {
    446 			jj = width(ii);
    447 			ws += jj;
    448 			numtabp[HP].val += jj;
    449 			widthp = jj;
    450 			*fp++ = ii;
    451 			if (fp > fbuf + FBUFSZ - 3) 
    452 				break;
    453 		}
    454 		*fp++ = ii;
    455 		*fp = 0;
    456 		if (type == RTAB)
    457 			length -= ws;
    458 		else 
    459 			length -= ws / 2; /*CTAB*/
    460 		pushback(fbuf);
    461 		if ((j = width(rchar)) != 0 && length > 0) {
    462 			int nchar = length / j;
    463 			while (nchar-- > 0 && pbp < &pbbuf[NC-3])
    464 				*pbp++ = rchar;
    465 			length %= j;
    466 		}
    467 		if (savepos > 0)
    468 			pushback(wbuf);
    469 		length = (length / HOR) * HOR;
    470 		jj = makem(length);
    471 		if (nlflg) {
    472 			if (ip == 0)
    473 				numtabp[CD].val--;
    474 			nlflg = 0;
    475 		}
    476 	}
    477 rtn:
    478 	gchtab[fc] &= ~FCBIT;
    479 	gchtab[tabch] &= ~TABBIT;
    480 	gchtab[ldrch] &= ~LDRBIT;
    481 	fc = savfc;
    482 	tabch = savtc;
    483 	ldrch = savlc;
    484 	gchtab[fc] |= FCBIT;
    485 	gchtab[tabch] = TABBIT;
    486 	gchtab[ldrch] |= LDRBIT;
    487 	numtabp[HP].val = savepos;
    488 	return(jj);
    489 }