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