1 #include "tdef.h"
2 #include "ext.h"
3 #include "fns.h"
4 
5 /*
6  * troff9.c
7  *
8  * misc functions
9  */
10 
setz(void)11 Tchar setz(void)
12 {
13 	Tchar i;
14 
15 	if (!ismot(i = getch()))
16 		i |= ZBIT;
17 	return(i);
18 }
19 
setline(void)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
eat(int c)79 eat(int c)
80 {
81 	int i;
82 
83 	while ((i = cbits(getch())) != c && i != '\n')
84 		;
85 	return(i);
86 }
87 
88 
setov(void)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 
setbra(void)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 
setvline(void)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 
setdraw(void)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 
casefc(void)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 
setfield(int x)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 }
490