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