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