xref: /titanic_50/usr/src/cmd/troff/n9.c (revision 71e32251703c729dbbebef2101770135584fd8d4)
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