xref: /illumos-gate/usr/src/cmd/troff/n9.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1989 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * University Copyright- Copyright (c) 1982, 1986, 1988
35  * The Regents of the University of California
36  * All Rights Reserved
37  *
38  * University Acknowledgment- Portions of this document are derived from
39  * software developed by the University of California, Berkeley, and its
40  * contributors.
41  */
42 
43 #include <libintl.h>
44 #include <stdlib.h>
45 
46 #include "tdef.h"
47 #ifdef NROFF
48 #include "tw.h"
49 #endif
50 #include "ext.h"
51 #ifdef EUC
52 #include <locale.h>
53 #include <wctype.h>
54 #include <langinfo.h>
55 
56 #define	ISO646	"646"
57 
58 int	multi_locale;
59 int	(*wdbdg)(wchar_t, wchar_t, int);
60 wchar_t	*(*wddlm)(wchar_t, wchar_t, int);
61 
62 int	csi_width[4] = {
63 	1,
64 	1,
65 	2,
66 	3,
67 };
68 #endif /* EUC */
69 
70 /*
71  * troff9.c
72  *
73  * misc functions
74  */
75 
76 tchar setz()
77 {
78 	tchar i;
79 
80 	if (!ismot(i = getch()))
81 		i |= ZBIT;
82 	return(i);
83 }
84 
85 setline()
86 {
87 	register tchar *i;
88 	tchar c;
89 	int	length;
90 	int	w, cnt, delim, rem, temp;
91 	tchar linebuf[NC];
92 
93 	if (ismot(c = getch()))
94 		return;
95 	delim = cbits(c);
96 	vflag = 0;
97 	dfact = EM;
98 	length = quant(atoi(), HOR);
99 	dfact = 1;
100 	if (!length) {
101 		eat(delim);
102 		return;
103 	}
104 s0:
105 	if ((cbits(c = getch())) == delim) {
106 		ch = c;
107 		c = RULE | chbits;
108 	} else if (cbits(c) == FILLER)
109 		goto s0;
110 	w = width(c);
111 	i = linebuf;
112 	if (length < 0) {
113 		*i++ = makem(length);
114 		length = -length;
115 	}
116 	if (!(cnt = length / w)) {
117 		*i++ = makem(-(temp = ((w - length) / 2)));
118 		*i++ = c;
119 		*i++ = makem(-(w - length - temp));
120 		goto s1;
121 	}
122 	if (rem = length % w) {
123 		if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN)
124 			*i++ = c | ZBIT;
125 		*i++ = makem(rem);
126 	}
127 	if (cnt) {
128 		*i++ = RPT;
129 		*i++ = cnt;
130 		*i++ = c;
131 	}
132 s1:
133 	*i++ = 0;
134 	eat(delim);
135 	pushback(linebuf);
136 }
137 
138 
139 eat(c)
140 register int	c;
141 {
142 	register i;
143 
144 	while ((i = cbits(getch())) != c &&  (i != '\n'))
145 		;
146 	return(i);
147 }
148 
149 
150 setov()
151 {
152 	register j, k;
153 	tchar i, o[NOV];
154 	int delim, w[NOV];
155 
156 	if (ismot(i = getch()))
157 		return;
158 	delim = cbits(i);
159 	for (k = 0; (k < NOV) && ((j = cbits(i = getch())) != delim) &&  (j != '\n'); k++) {
160 		o[k] = i;
161 		w[k] = width(i);
162 	}
163 	o[k] = w[k] = 0;
164 	if (o[0])
165 		for (j = 1; j; ) {
166 			j = 0;
167 			for (k = 1; o[k] ; k++) {
168 				if (w[k-1] < w[k]) {
169 					j++;
170 					i = w[k];
171 					w[k] = w[k-1];
172 					w[k-1] = i;
173 					i = o[k];
174 					o[k] = o[k-1];
175 					o[k-1] = i;
176 				}
177 			}
178 		}
179 	else
180 		return;
181 	*pbp++ = makem(w[0] / 2);
182 	for (k = 0; o[k]; k++)
183 		;
184 	while (k>0) {
185 		k--;
186 		*pbp++ = makem(-((w[k] + w[k+1]) / 2));
187 		*pbp++ = o[k];
188 	}
189 }
190 
191 
192 setbra()
193 {
194 	register k;
195 	tchar i, *j, dwn;
196 	int	cnt, delim;
197 	tchar brabuf[NC];
198 
199 	if (ismot(i = getch()))
200 		return;
201 	delim = cbits(i);
202 	j = brabuf + 1;
203 	cnt = 0;
204 #ifdef NROFF
205 	dwn = (2 * t.Halfline) | MOT | VMOT;
206 #endif
207 #ifndef NROFF
208 	dwn = EM | MOT | VMOT;
209 #endif
210 	while (((k = cbits(i = getch())) != delim) && (k != '\n') &&  (j <= (brabuf + NC - 4))) {
211 		*j++ = i | ZBIT;
212 		*j++ = dwn;
213 		cnt++;
214 	}
215 	if (--cnt < 0)
216 		return;
217 	else if (!cnt) {
218 		ch = *(j - 2);
219 		return;
220 	}
221 	*j = 0;
222 #ifdef NROFF
223 	*--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT;
224 #endif
225 #ifndef NROFF
226 	*--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT;
227 #endif
228 	*--j &= ~ZBIT;
229 	pushback(brabuf);
230 }
231 
232 
233 setvline()
234 {
235 	register i;
236 	tchar c, rem, ver, neg;
237 	int	cnt, delim, v;
238 	tchar vlbuf[NC];
239 	register tchar *vlp;
240 
241 	if (ismot(c = getch()))
242 		return;
243 	delim = cbits(c);
244 	dfact = lss;
245 	vflag++;
246 	i = quant(atoi(), VERT);
247 	dfact = 1;
248 	if (!i) {
249 		eat(delim);
250 		vflag = 0;
251 		return;
252 	}
253 	if ((cbits(c = getch())) == delim) {
254 		c = BOXRULE | chbits;	/*default box rule*/
255 	} else
256 		getch();
257 	c |= ZBIT;
258 	neg = 0;
259 	if (i < 0) {
260 		i = -i;
261 		neg = NMOT;
262 	}
263 #ifdef NROFF
264 	v = 2 * t.Halfline;
265 #endif
266 #ifndef NROFF
267 	v = EM;
268 #endif
269 	cnt = i / v;
270 	rem = makem(i % v) | neg;
271 	ver = makem(v) | neg;
272 	vlp = vlbuf;
273 	if (!neg)
274 		*vlp++ = ver;
275 	if (absmot(rem) != 0) {
276 		*vlp++ = c;
277 		*vlp++ = rem;
278 	}
279 	while ((vlp < (vlbuf + NC - 3)) && cnt--) {
280 		*vlp++ = c;
281 		*vlp++ = ver;
282 	}
283 	*(vlp - 2) &= ~ZBIT;
284 	if (!neg)
285 		vlp--;
286 	*vlp++ = 0;
287 	pushback(vlbuf);
288 	vflag = 0;
289 }
290 
291 #define	NPAIR	(NC/2-6)	/* max pairs in spline, etc. */
292 
293 setdraw()	/* generate internal cookies for a drawing function */
294 {
295 	int i, j, k, dx[NPAIR], dy[NPAIR], delim, type;
296 	tchar c, drawbuf[NC];
297 
298 	/* input is \D'f dx dy dx dy ... c' (or at least it had better be) */
299 	/* this does drawing function f with character c and the */
300 	/* specified dx,dy pairs interpreted as appropriate */
301 	/* pairs are deltas from last point, except for radii */
302 
303 	/* l dx dy:	line from here by dx,dy */
304 	/* c x:		circle of diameter x, left side here */
305 	/* e x y:	ellipse of diameters x,y, left side here */
306 	/* a dx1 dy1 dx2 dy2:
307 			ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */
308 	/* ~ dx1 dy1 dx2 dy2...:
309 			spline to dx1,dy1 to dx2,dy2 ... */
310 	/* f dx dy ...:	f is any other char:  like spline */
311 
312 	if (ismot(c = getch()))
313 		return;
314 	delim = cbits(c);
315 	type = cbits(getch());
316 	for (i = 0; i < NPAIR ; i++) {
317 		c = getch();
318 		if (cbits(c) == delim)
319 			break;
320 	/* ought to pick up optional drawing character */
321 		if (cbits(c) != ' ')
322 			ch = c;
323 		vflag = 0;
324 		dfact = EM;
325 		dx[i] = quant(atoi(), HOR);
326 		if (dx[i] > MAXMOT)
327 			dx[i] = MAXMOT;
328 		else if (dx[i] < -MAXMOT)
329 			dx[i] = -MAXMOT;
330 		if (cbits((c = getch())) == delim) {	/* spacer */
331 			dy[i++] = 0;
332 			break;
333 		}
334 		vflag = 1;
335 		dfact = lss;
336 		dy[i] = quant(atoi(), VERT);
337 		if (dy[i] > MAXMOT)
338 			dy[i] = MAXMOT;
339 		else if (dy[i] < -MAXMOT)
340 			dy[i] = -MAXMOT;
341 	}
342 	dfact = 1;
343 	vflag = 0;
344 #ifndef NROFF
345 	drawbuf[0] = DRAWFCN | chbits | ZBIT;
346 	drawbuf[1] = type | chbits | ZBIT;
347 	drawbuf[2] = '.' | chbits | ZBIT;	/* use default drawing character */
348 	for (k = 0, j = 3; k < i; k++) {
349 		drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k]));
350 		drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k]));
351 	}
352 	if (type == DRAWELLIPSE) {
353 		drawbuf[5] = drawbuf[4] | NMOT;	/* so the net vertical is zero */
354 		j = 6;
355 	}
356 	drawbuf[j++] = DRAWFCN | chbits | ZBIT;	/* marks end for ptout */
357 	drawbuf[j] = 0;
358 	pushback(drawbuf);
359 #endif
360 }
361 
362 
363 casefc()
364 {
365 	register i;
366 	tchar j;
367 
368 	gchtab[fc] &= ~FCBIT;
369 	fc = IMP;
370 	padc = ' ';
371 	if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n')
372 		return;
373 	fc = i;
374 	gchtab[fc] |= FCBIT;
375 	if (skip() || ismot(ch) || (ch = cbits(ch)) == fc)
376 		return;
377 	padc = ch;
378 }
379 
380 
381 tchar
382 setfield(x)
383 int	x;
384 {
385 	register tchar ii, jj, *fp;
386 	register i, j;
387 	int length, ws, npad, temp, type;
388 	tchar **pp, *padptr[NPP];
389 	tchar fbuf[FBUFSZ];
390 	int savfc, savtc, savlc;
391 	tchar rchar;
392 	int savepos;
393 
394 	if (x == tabch)
395 		rchar = tabc | chbits;
396 	else if (x ==  ldrch)
397 		rchar = dotc | chbits;
398 	temp = npad = ws = 0;
399 	savfc = fc;
400 	savtc = tabch;
401 	savlc = ldrch;
402 	tabch = ldrch = fc = IMP;
403 	savepos = numtab[HP].val;
404 	gchtab[tabch] &= ~TABBIT;
405 	gchtab[ldrch] &= ~LDRBIT;
406 	gchtab[fc] &= ~FCBIT;
407 	gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
408 	for (j = 0; ; j++) {
409 		if ((tabtab[j] & TABMASK) == 0) {
410 			if (x == savfc)
411 				errprint(gettext("zero field width."));
412 			jj = 0;
413 			goto rtn;
414 		}
415 		if ((length = ((tabtab[j] & TABMASK) - numtab[HP].val)) > 0 )
416 			break;
417 	}
418 	type = tabtab[j] & (~TABMASK);
419 	fp = fbuf;
420 	pp = padptr;
421 	if (x == savfc) {
422 		while (1) {
423 			j = cbits(ii = getch());
424 			jj = width(ii);
425 			widthp = jj;
426 			numtab[HP].val += jj;
427 			if (j == padc) {
428 				npad++;
429 				*pp++ = fp;
430 				if (pp > (padptr + NPP - 1))
431 					break;
432 				goto s1;
433 			} else if (j == savfc)
434 				break;
435 			else if (j == '\n') {
436 				temp = j;
437 				nlflg = 0;
438 				break;
439 			}
440 			ws += jj;
441 s1:
442 			*fp++ = ii;
443 			if (fp > (fbuf + FBUFSZ - 3))
444 				break;
445 		}
446 		if (!npad) {
447 			npad++;
448 			*pp++ = fp;
449 			*fp++ = 0;
450 		}
451 		*fp++ = temp;
452 		*fp++ = 0;
453 		temp = i = (j = length - ws) / npad;
454 		i = (i / HOR) * HOR;
455 		if ((j -= i * npad) < 0)
456 			j = -j;
457 		ii = makem(i);
458 		if (temp < 0)
459 			ii |= NMOT;
460 		for (; npad > 0; npad--) {
461 			*(*--pp) = ii;
462 			if (j) {
463 				j -= HOR;
464 				(*(*pp)) += HOR;
465 			}
466 		}
467 		pushback(fbuf);
468 		jj = 0;
469 	} else if (type == 0) {
470 		/*plain tab or leader*/
471 		if ((j = width(rchar)) > 0) {
472 			int nchar = length / j;
473 			while (nchar-->0 && pbp < &pbbuf[NC-3]) {
474 				numtab[HP].val += j;
475 				widthp = j;
476 				*pbp++ = rchar;
477 			}
478 			length %= j;
479 		}
480 		if (length)
481 			jj = length | MOT;
482 		else
483 			jj = getch0();
484 	} else {
485 		/*center tab*/
486 		/*right tab*/
487 		while (((j = cbits(ii = getch())) != savtc) &&  (j != '\n') && (j != savlc)) {
488 			jj = width(ii);
489 			ws += jj;
490 			numtab[HP].val += jj;
491 			widthp = jj;
492 			*fp++ = ii;
493 			if (fp > (fbuf + FBUFSZ - 3))
494 				break;
495 		}
496 		*fp++ = ii;
497 		*fp++ = 0;
498 		if (type == RTAB)
499 			length -= ws;
500 		else
501 			length -= ws / 2; /*CTAB*/
502 		pushback(fbuf);
503 		if ((j = width(rchar)) != 0 && length > 0) {
504 			int nchar = length / j;
505 			while (nchar-- > 0 && pbp < &pbbuf[NC-3])
506 				*pbp++ = rchar;
507 			length %= j;
508 		}
509 		length = (length / HOR) * HOR;
510 		jj = makem(length);
511 		nlflg = 0;
512 	}
513 rtn:
514 	gchtab[fc] &= ~FCBIT;
515 	gchtab[tabch] &= ~TABBIT;
516 	gchtab[ldrch] &= ~LDRBIT;
517 	fc = savfc;
518 	tabch = savtc;
519 	ldrch = savlc;
520 	gchtab[fc] |= FCBIT;
521 	gchtab[tabch] = TABBIT;
522 	gchtab[ldrch] |= LDRBIT;
523 	numtab[HP].val = savepos;
524 	return(jj);
525 }
526 
527 
528 #ifdef EUC
529 #ifdef NROFF
530 /* locale specific initialization */
531 int localize()
532 {
533 	extern int	wdbindf();
534 	extern wchar_t	*wddelim();
535 	char	*codeset;
536 
537 	codeset = nl_langinfo(CODESET);
538 
539 	if (MB_CUR_MAX > 1)
540 		multi_locale = 1;
541 	else {
542 		if (*codeset == '\0' ||
543 			(strcmp(codeset, ISO646) == 0)) {
544 			/*
545 			 * if codeset is an empty string
546 			 * assumes this is C locale (7-bit) locale.
547 			 * This happens in 2.5, 2.5.1, and 2.6 system
548 			 * Or, if codeset is "646"
549 			 * this is 7-bit locale.
550 			 */
551 			multi_locale = 0;
552 		} else {
553 			/* 8-bit locale */
554 			multi_locale = 1;
555 		}
556 
557 	}
558 	wdbdg = wdbindf;
559 	wddlm = wddelim;
560 }
561 #endif /* EUC */
562 #endif /* NROFF */
563