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#include <libintl.h>
40#include <stdlib.h>
41
42#include "tdef.h"
43#ifdef NROFF
44#include "tw.h"
45#endif
46#include "ext.h"
47#ifdef EUC
48#include <locale.h>
49#include <wctype.h>
50#include <langinfo.h>
51
52#define	ISO646	"646"
53
54int	multi_locale;
55int	(*wdbdg)(wchar_t, wchar_t, int);
56wchar_t	*(*wddlm)(wchar_t, wchar_t, int);
57
58int	csi_width[4] = {
59	1,
60	1,
61	2,
62	3,
63};
64#endif /* EUC */
65
66/*
67 * troff9.c
68 *
69 * misc functions
70 */
71
72tchar
73setz(void)
74{
75	tchar i;
76
77	if (!ismot(i = getch()))
78		i |= ZBIT;
79	return (i);
80}
81
82int
83setline(void)
84{
85	tchar *i;
86	tchar c;
87	int	length;
88	int	w, cnt, delim, rem, temp;
89	tchar linebuf[NC];
90
91	if (ismot(c = getch()))
92		return (0);
93	delim = cbits(c);
94	vflag = 0;
95	dfact = EM;
96	length = quant(atoi(), HOR);
97	dfact = 1;
98	if (!length) {
99		eat(delim);
100		return (0);
101	}
102s0:
103	if ((cbits(c = getch())) == delim) {
104		ch = c;
105		c = RULE | chbits;
106	} else if (cbits(c) == FILLER)
107		goto s0;
108	w = width(c);
109	i = linebuf;
110	if (length < 0) {
111		*i++ = makem(length);
112		length = -length;
113	}
114	if (!(cnt = length / w)) {
115		*i++ = makem(-(temp = ((w - length) / 2)));
116		*i++ = c;
117		*i++ = makem(-(w - length - temp));
118		goto s1;
119	}
120	if (rem = length % w) {
121		if (cbits(c) == RULE || cbits(c) == UNDERLINE ||
122		    cbits(c) == ROOTEN)
123			*i++ = c | ZBIT;
124		*i++ = makem(rem);
125	}
126	if (cnt) {
127		*i++ = RPT;
128		*i++ = cnt;
129		*i++ = c;
130	}
131s1:
132	*i++ = 0;
133	eat(delim);
134	pushback(linebuf);
135
136	return (0);
137}
138
139
140int
141eat(int c)
142{
143	int	i;
144
145	while ((i = cbits(getch())) != c && (i != '\n'))
146		;
147	return (i);
148}
149
150
151int
152setov(void)
153{
154	int	j, k;
155	tchar i, o[NOV];
156	int delim, w[NOV];
157
158	if (ismot(i = getch()))
159		return (0);
160	delim = cbits(i);
161	for (k = 0; (k < NOV) && ((j = cbits(i = getch())) != delim) &&
162	    (j != '\n'); k++) {
163		o[k] = i;
164		w[k] = width(i);
165	}
166	if (k >= NOV) {
167		k = NOV - 1;
168	}
169	o[k] = w[k] = 0;
170	if (o[0])
171		for (j = 1; j; ) {
172			j = 0;
173			for (k = 1; o[k]; k++) {
174				if (w[k-1] < w[k]) {
175					j++;
176					i = w[k];
177					w[k] = w[k-1];
178					w[k-1] = i;
179					i = o[k];
180					o[k] = o[k-1];
181					o[k-1] = i;
182				}
183			}
184		}
185	else
186		return (0);
187	*pbp++ = makem(w[0] / 2);
188	for (k = 0; o[k]; k++)
189		;
190	while (k > 0) {
191		k--;
192		*pbp++ = makem(-((w[k] + w[k+1]) / 2));
193		*pbp++ = o[k];
194	}
195
196	return (0);
197}
198
199
200int
201setbra(void)
202{
203	int	k;
204	tchar i, *j, dwn;
205	int	cnt, delim;
206	tchar brabuf[NC];
207
208	if (ismot(i = getch()))
209		return (0);
210	delim = cbits(i);
211	j = brabuf + 1;
212	cnt = 0;
213#ifdef NROFF
214	dwn = (2 * t.Halfline) | MOT | VMOT;
215#endif
216#ifndef NROFF
217	dwn = EM | MOT | VMOT;
218#endif
219	while (((k = cbits(i = getch())) != delim) && (k != '\n') &&
220	    (j <= (brabuf + NC - 4))) {
221		*j++ = i | ZBIT;
222		*j++ = dwn;
223		cnt++;
224	}
225	if (--cnt < 0)
226		return (0);
227	else if (!cnt) {
228		ch = *(j - 2);
229		return (0);
230	}
231	*j = 0;
232#ifdef NROFF
233	*--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT;
234#endif
235#ifndef NROFF
236	*--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT;
237#endif
238	*--j &= ~ZBIT;
239	pushback(brabuf);
240
241	return (0);
242}
243
244
245int
246setvline(void)
247{
248	int	i;
249	tchar c, rem, ver, neg;
250	int	cnt, delim, v;
251	tchar vlbuf[NC];
252	tchar *vlp;
253
254	if (ismot(c = getch()))
255		return (0);
256	delim = cbits(c);
257	dfact = lss;
258	vflag++;
259	i = quant(atoi(), VERT);
260	dfact = 1;
261	if (!i) {
262		eat(delim);
263		vflag = 0;
264		return (0);
265	}
266	if ((cbits(c = getch())) == delim) {
267		c = BOXRULE | chbits;	/* default box rule */
268	} else
269		getch();
270	c |= ZBIT;
271	neg = 0;
272	if (i < 0) {
273		i = -i;
274		neg = NMOT;
275	}
276#ifdef NROFF
277	v = 2 * t.Halfline;
278#endif
279#ifndef NROFF
280	v = EM;
281#endif
282	cnt = i / v;
283	rem = makem(i % v) | neg;
284	ver = makem(v) | neg;
285	vlp = vlbuf;
286	if (!neg)
287		*vlp++ = ver;
288	if (absmot(rem) != 0) {
289		*vlp++ = c;
290		*vlp++ = rem;
291	}
292	while ((vlp < (vlbuf + NC - 3)) && cnt--) {
293		*vlp++ = c;
294		*vlp++ = ver;
295	}
296	*(vlp - 2) &= ~ZBIT;
297	if (!neg)
298		vlp--;
299	*vlp++ = 0;
300	pushback(vlbuf);
301	vflag = 0;
302
303	return (0);
304}
305
306#define	NPAIR	(NC/2-6)	/* max pairs in spline, etc. */
307
308/*
309 * Generate internal cookies for a drawing function.
310 */
311int
312setdraw(void)
313{
314	int i, j, k, dx[NPAIR], dy[NPAIR], delim, type __unused;
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
389int
390casefc(void)
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
410tchar
411setfield(int x)
412{
413	tchar ii, jj, *fp;
414	int	i, j;
415	int length, ws, npad, temp, type;
416	tchar **pp, *padptr[NPP];
417	tchar fbuf[FBUFSZ];
418	int savfc, savtc, savlc;
419	tchar rchar;
420	int savepos;
421
422	if (x == tabch)
423		rchar = tabc | chbits;
424	else if (x ==  ldrch)
425		rchar = dotc | chbits;
426	temp = npad = ws = 0;
427	savfc = fc;
428	savtc = tabch;
429	savlc = ldrch;
430	tabch = ldrch = fc = IMP;
431	savepos = numtab[HP].val;
432	gchtab[tabch] &= ~TABBIT;
433	gchtab[ldrch] &= ~LDRBIT;
434	gchtab[fc] &= ~FCBIT;
435	gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
436	for (j = 0; ; j++) {
437		if ((tabtab[j] & TABMASK) == 0) {
438			if (x == savfc)
439				errprint(gettext("zero field width."));
440			jj = 0;
441			goto rtn;
442		}
443		if ((length = ((tabtab[j] & TABMASK) - numtab[HP].val)) > 0)
444			break;
445	}
446	type = tabtab[j] & (~TABMASK);
447	fp = fbuf;
448	pp = padptr;
449	if (x == savfc) {
450		while (1) {
451			j = cbits(ii = getch());
452			jj = width(ii);
453			widthp = jj;
454			numtab[HP].val += jj;
455			if (j == padc) {
456				npad++;
457				*pp++ = fp;
458				if (pp > (padptr + NPP - 1))
459					break;
460				goto s1;
461			} else if (j == savfc)
462				break;
463			else if (j == '\n') {
464				temp = j;
465				nlflg = 0;
466				break;
467			}
468			ws += jj;
469s1:
470			*fp++ = ii;
471			if (fp > (fbuf + FBUFSZ - 3))
472				break;
473		}
474		if (!npad) {
475			npad++;
476			*pp++ = fp;
477			*fp++ = 0;
478		}
479		*fp++ = temp;
480		*fp++ = 0;
481		temp = i = (j = length - ws) / npad;
482		i = (i / HOR) * HOR;
483		if ((j -= i * npad) < 0)
484			j = -j;
485		ii = makem(i);
486		if (temp < 0)
487			ii |= NMOT;
488		for (; npad > 0; npad--) {
489			*(*--pp) = ii;
490			if (j) {
491				j -= HOR;
492				(*(*pp)) += HOR;
493			}
494		}
495		pushback(fbuf);
496		jj = 0;
497	} else if (type == 0) {
498		/* plain tab or leader */
499		if ((j = width(rchar)) > 0) {
500			int nchar = length / j;
501			while (nchar-->0 && pbp < &pbbuf[NC-3]) {
502				numtab[HP].val += j;
503				widthp = j;
504				*pbp++ = rchar;
505			}
506			length %= j;
507		}
508		if (length)
509			jj = length | MOT;
510		else
511			jj = getch0();
512	} else {
513		/* center tab */
514		/* right tab */
515		while (((j = cbits(ii = getch())) != savtc) &&
516		    (j != '\n') && (j != savlc)) {
517			jj = width(ii);
518			ws += jj;
519			numtab[HP].val += jj;
520			widthp = jj;
521			*fp++ = ii;
522			if (fp > (fbuf + FBUFSZ - 3))
523				break;
524		}
525		*fp++ = ii;
526		*fp++ = 0;
527		if (type == RTAB)
528			length -= ws;
529		else
530			length -= ws / 2; /* CTAB */
531		pushback(fbuf);
532		if ((j = width(rchar)) != 0 && length > 0) {
533			int nchar = length / j;
534			while (nchar-- > 0 && pbp < &pbbuf[NC-3])
535				*pbp++ = rchar;
536			length %= j;
537		}
538		length = (length / HOR) * HOR;
539		jj = makem(length);
540		nlflg = 0;
541	}
542rtn:
543	gchtab[fc] &= ~FCBIT;
544	gchtab[tabch] &= ~TABBIT;
545	gchtab[ldrch] &= ~LDRBIT;
546	fc = savfc;
547	tabch = savtc;
548	ldrch = savlc;
549	gchtab[fc] |= FCBIT;
550	gchtab[tabch] = TABBIT;
551	gchtab[ldrch] |= LDRBIT;
552	numtab[HP].val = savepos;
553	return (jj);
554}
555
556
557#ifdef EUC
558#ifdef NROFF
559/* locale specific initialization */
560int
561localize(void)
562{
563	extern int	wdbindf();
564	extern wchar_t	*wddelim();
565	char	*codeset;
566
567	codeset = nl_langinfo(CODESET);
568
569	if (MB_CUR_MAX > 1)
570		multi_locale = 1;
571	else {
572		if (*codeset == '\0' ||
573		    (strcmp(codeset, ISO646) == 0)) {
574			/*
575			 * if codeset is an empty string
576			 * assumes this is C locale (7-bit) locale.
577			 * This happens in 2.5, 2.5.1, and 2.6 system
578			 * Or, if codeset is "646"
579			 * this is 7-bit locale.
580			 */
581			multi_locale = 0;
582		} else {
583			/* 8-bit locale */
584			multi_locale = 1;
585		}
586
587	}
588	wdbdg = wdbindf;
589	wddlm = wddelim;
590
591	return (0);
592}
593#endif /* EUC */
594#endif /* NROFF */
595