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 2003 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/*
43n10.c
44
45Device interfaces
46*/
47
48#include <limits.h>
49#include <ctype.h>
50#include <sys/types.h>
51#include <sys/stat.h>
52#ifdef EUC
53#ifdef NROFF
54#include <stdlib.h>
55#endif /* NROFF */
56#endif /* EUC */
57#include "tdef.h"
58#include "ext.h"
59#include "tw.h"
60
61struct t t;	/* terminal characteristics */
62
63int	dtab;
64int	plotmode;
65int	esct;
66
67char	xchname[4 * (NROFFCHARS-_SPECCHAR_ST)];	/* hy, em, etc. */
68short	xchtab[NROFFCHARS-_SPECCHAR_ST];		/* indexes into chname[] */
69char	*codestr;
70char	*chname = xchname;
71short	*chtab = xchtab;
72int	nchtab = 0;
73
74
75int	Inch;
76int	Hor;
77int	Vert;
78int	nfonts	= 4;	/* R, I, B, S */
79
80/* these characters are used as various signals or values
81 * in miscellaneous places.
82 * values are set in specnames in t10.c
83 */
84
85int	c_hyphen;
86int	c_emdash;
87int	c_rule;
88int	c_minus;
89int	c_fi;
90int	c_fl;
91int	c_ff;
92int	c_ffi;
93int	c_ffl;
94int	c_acute;
95int	c_grave;
96int	c_under;
97int	c_rooten;
98int	c_boxrule;
99int	c_lefthand;
100int	c_dagger;
101int	c_isalnum;
102
103int
104ptinit()
105{
106	int i, j;
107	char *p, *cp, *q;
108	int nread, fd;
109	extern char *skipstr(), *getstr(), *getint();
110	extern char *setbrk();
111	struct stat stbuf;
112	char check[50];
113
114	strcat(termtab, devname);
115	if ((fd = open(termtab, 0)) < 0) {
116		errprint(gettext("cannot open %s"), termtab);
117		exit(-1);
118	}
119
120	fstat(fd, &stbuf);
121	codestr = setbrk((int) stbuf.st_size);
122
123	nread = read(fd, codestr, (int) stbuf.st_size);
124	close(fd);
125
126	p = codestr;
127	p = skipstr(p);		/* skip over type, could check */
128	p = skipstr(p); p = getint(p, &t.bset);
129	p = skipstr(p); p = getint(p, &t.breset);
130	p = skipstr(p); p = getint(p, &t.Hor);
131	p = skipstr(p); p = getint(p, &t.Vert);
132	p = skipstr(p); p = getint(p, &t.Newline);
133	p = skipstr(p); p = getint(p, &t.Char);
134	p = skipstr(p); p = getint(p, &t.Em);
135	p = skipstr(p); p = getint(p, &t.Halfline);
136	p = skipstr(p); p = getint(p, &t.Adj);
137	p = skipstr(p); p = getstr(p, t.twinit = p);
138	p = skipstr(p); p = getstr(p, t.twrest = p);
139	p = skipstr(p); p = getstr(p, t.twnl = p);
140	p = skipstr(p); p = getstr(p, t.hlr = p);
141	p = skipstr(p); p = getstr(p, t.hlf = p);
142	p = skipstr(p); p = getstr(p, t.flr = p);
143	p = skipstr(p); p = getstr(p, t.bdon = p);
144	p = skipstr(p); p = getstr(p, t.bdoff = p);
145	p = skipstr(p); p = getstr(p, t.iton = p);
146	p = skipstr(p); p = getstr(p, t.itoff = p);
147	p = skipstr(p); p = getstr(p, t.ploton = p);
148	p = skipstr(p); p = getstr(p, t.plotoff = p);
149	p = skipstr(p); p = getstr(p, t.up = p);
150	p = skipstr(p); p = getstr(p, t.down = p);
151	p = skipstr(p); p = getstr(p, t.right = p);
152	p = skipstr(p); p = getstr(p, t.left = p);
153
154	getstr(p, check);
155	if (strcmp(check, "charset") != 0) {
156		errprint(gettext("device table apparently curdled"));
157		exit(1);
158	}
159
160	for (i = 0; i < _SPECCHAR_ST; i++)
161		t.width[i] = 1;	/* default widths */
162
163	i = 0;
164/* this ought to be a pointer array and in place in codestr */
165	cp = chname + 1;	/* bug if starts at 0, in setch */
166	while (p < codestr + nread) {
167		while (*p == ' ' || *p == '\t' || *p == '\n')
168			p++;
169		if (i + _SPECCHAR_ST >= NROFFCHARS) {
170			errprint(gettext("too many names in charset for %s"),
171					 termtab);
172			exit(1);
173		}
174		chtab[i] = cp - chname;	/* index, not pointer */
175		*cp++ = *p++;	/* 2-char names */
176		*cp++ = *p++;
177		*cp++ = '\0';
178		while (*p == ' ' || *p == '\t')
179			p++;
180		t.width[i+_SPECCHAR_ST] = *p++ - '0';
181		while (*p == ' ' || *p == '\t')
182			p++;
183		t.codetab[i] = p;
184		p = getstr(p, p);	/* compress string */
185		p++;
186		i++;
187		nchtab++;
188	}
189
190	sps = EM;
191	ics = EM * 2;
192	dtab = 8 * t.Em;
193	for (i = 0; i < 16; i++)
194		tabtab[i] = dtab * (i + 1);
195	pl = 11 * INCH;
196	po = PO;
197	spacesz = SS;
198	lss = lss1 = VS;
199	ll = ll1 = lt = lt1 = LL;
200	smnt = nfonts = 5;	/* R I B BI S */
201	specnames();	/* install names like "hyphen", etc. */
202	if (eqflg)
203		t.Adj = t.Hor;
204
205	return (0);
206}
207
208char *skipstr(s)	/* skip over leading space plus string */
209	char *s;
210{
211	while (*s == ' ' || *s == '\t' || *s == '\n')
212		s++;
213	while (*s != ' ' && *s != '\t' && *s != '\n')
214		if (*s++ == '\\')
215			s++;
216	return s;
217}
218
219char *getstr(s, t)	/* find next string in s, copy to t */
220	char *s, *t;
221{
222	int quote = 0;
223
224	while (*s == ' ' || *s == '\t' || *s == '\n')
225		s++;
226	if (*s == '"') {
227		s++;
228		quote = 1;
229	}
230	for (;;) {
231		if (quote && *s == '"') {
232			s++;
233			break;
234		}
235		if (!quote && (*s == ' ' || *s == '\t' || *s == '\n'))
236			break;
237		if (*s != '\\')
238			*t++ = *s++;
239		else {
240			s++;	/* skip \\ */
241			if (isdigit((unsigned char)s[0]) &&
242			    isdigit((unsigned char)s[1]) &&
243			    isdigit((unsigned char)s[2])) {
244				*t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0';
245				s += 2;
246			} else if (isdigit((unsigned char)s[0])) {
247				*t++ = *s - '0';
248			} else if (*s == 'b') {
249				*t++ = '\b';
250			} else if (*s == 'n') {
251				*t++ = '\n';
252			} else if (*s == 'r') {
253				*t++ = '\r';
254			} else if (*s == 't') {
255				*t++ = '\t';
256			} else {
257				*t++ = *s;
258			}
259			s++;
260		}
261	}
262	*t = '\0';
263	return s;
264}
265
266char *getint(s, pn)	/* find integer at s */
267	char *s;
268	int *pn;
269{
270	int base;
271
272	while (*s == ' ' || *s == '\t' || *s == '\n')
273		s++;
274	base = (*s == '0') ? 8 : 10;
275	*pn = 0;
276	while (isdigit((unsigned char)*s))
277		*pn = base * *pn + *s++ - '0';
278	return s;
279}
280
281int
282specnames()
283{
284	static struct {
285		int	*n;
286		char	*v;
287	} spnames[] = {
288		&c_hyphen, "hy",
289		&c_emdash, "em",
290		&c_rule, "ru",
291		&c_minus, "\\-",
292		&c_fi, "fi",
293		&c_fl, "fl",
294		&c_ff, "ff",
295		&c_ffi, "Fi",
296		&c_ffl, "Fl",
297		&c_acute, "aa",
298		&c_grave, "ga",
299		&c_under, "ul",
300		&c_rooten, "rn",
301		&c_boxrule, "br",
302		&c_lefthand, "lh",
303		&c_isalnum, "__",
304		0, 0
305	};
306	int	i;
307
308	for (i = 0; spnames[i].n; i++)
309		*spnames[i].n = findch(spnames[i].v);
310	if (c_isalnum == 0)
311		c_isalnum = NROFFCHARS;
312
313	return (0);
314}
315
316
317int
318findch(s)	/* find char s in chname */
319char	*s;
320{
321	int	i;
322
323	for (i = 0; chtab[i] != 0; i++)
324		if (strcmp(s, &chname[chtab[i]]) == 0)
325			return(i + _SPECCHAR_ST);
326	return(0);
327}
328
329int
330twdone()
331{
332	int waitf;
333
334	obufp = obuf;
335	if (t.twrest)		/* has ptinit() been done yet? */
336		oputs(t.twrest);
337	flusho();
338	if (pipeflg) {
339		close(ptid);
340		wait(&waitf);
341	}
342	restore_tty();
343
344	return (0);
345}
346
347
348int
349ptout(i)
350	tchar i;
351{
352	*olinep++ = i;
353	if (olinep >= &oline[LNSIZE])
354		olinep--;
355	if (cbits(i) != '\n')
356		return (0);
357	olinep--;
358	lead += dip->blss + lss - t.Newline;
359	dip->blss = 0;
360	esct = esc = 0;
361	if (olinep > oline) {
362		move();
363		ptout1();
364		oputs(t.twnl);
365	} else {
366		lead += t.Newline;
367		move();
368	}
369	lead += dip->alss;
370	dip->alss = 0;
371	olinep = oline;
372
373	return (0);
374}
375
376
377int
378ptout1()
379{
380	int	k;
381	char	*codep;
382#ifdef EUC
383#ifdef NROFF
384	int cnt;
385	tchar *qq;
386#endif /* NROFF */
387#endif /* EUC */
388	extern char	*plot();
389	int	w, j, phyw;
390#ifdef EUC
391#ifdef NROFF
392	int jj;
393#endif /* NROFF */
394#endif /* EUC */
395	tchar * q, i;
396	static int oxfont = FT;	/* start off in roman */
397
398	for (q = oline; q < olinep; q++) {
399		i = *q;
400		if (ismot(i)) {
401			j = absmot(i);
402			if (isnmot(i))
403				j = -j;
404			if (isvmot(i))
405				lead += j;
406			else
407				esc += j;
408			continue;
409		}
410		if ((k = cbits(i)) <= 040) {
411			switch (k) {
412			case ' ': /*space*/
413				esc += t.Char;
414				break;
415			case '\033':
416			case '\007':
417			case '\016':
418			case '\017':
419				oput(k);
420				break;
421			}
422			continue;
423		}
424#ifdef EUC
425#ifdef NROFF
426		if (multi_locale && ((k & MBMASK) || (k & CSMASK))) {
427			cnt = 0;
428			while ((*q & MBMASK1) && (cnt + 1 < (int)MB_CUR_MAX)) {
429				cnt++;
430				q++;
431			}
432			if ((cnt && !(*q & CSMASK)) || (*q & MBMASK1)) {
433				q -= cnt;
434				cnt = 0;
435				*q &= ~0xfe00;
436			}
437			k = cbits(i = *q);
438			phyw = w = t.Char * csi_width[cs(i)];
439		} else {
440#endif /* NROFF */
441#endif /* EUC */
442		phyw = w = t.Char * t.width[k];
443		if (iszbit(i))
444			w = 0;
445#ifdef EUC
446#ifdef NROFF
447		}
448#endif /* NROFF */
449#endif /* EUC */
450		if (esc || lead)
451			move();
452		esct += w;
453#ifndef EUC
454		xfont = fbits(i);
455#else
456#ifndef NROFF
457		xfont = fbits(i);
458#else
459#endif /* NROFF */
460		xfont = (fbits(*q) % NFONT);	/* for invalid code */
461#endif /* EUC */
462		if (xfont != oxfont) {
463			if (oxfont == ulfont || oxfont == BIFONT)
464				oputs(t.itoff);
465			if (bdtab[oxfont])
466				oputs(t.bdoff);
467			if (xfont == ulfont || xfont == BIFONT)
468				oputs(t.iton);
469			if (bdtab[xfont])
470				oputs(t.bdon);
471			oxfont = xfont;
472		}
473		if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) {
474			for (j = w / t.Char; j > 0; j--)
475				oput('_');
476			for (j = w / t.Char; j > 0; j--)
477				oput('\b');
478		}
479		if ((j = bdtab[xfont]) && !(*t.bdon & 0377))
480			j++;
481		else
482			j = 1;	/* number of overstrikes for bold */
483		if (k < 128) {	/* ordinary ascii */
484			oput(k);
485			while (--j > 0) {
486				oput('\b');
487				oput(k);
488			}
489#ifdef EUC
490#ifdef NROFF
491		} else if (multi_locale && (k & CSMASK)) {
492			for (qq = q - cnt; qq <= q;)
493				oput(cbits(*qq++));
494			while (--j > 0) {
495				for (jj = cnt + 1; jj > 0; jj--)
496					oput('\b');
497				for (qq = q - cnt; qq <= q;)
498					oput(cbits(*qq++));
499			}
500		} else if (k < 256) {
501			/*
502			 * Invalid character for C locale or
503			 * non-printable 8-bit single byte
504			 * character such as <no-break-sp>
505			 * in ISO-8859-1
506			 */
507			oput(k);
508			while (--j > 0) {
509				oput('\b');
510				oput(k);
511			}
512#endif /* NROFF */
513#endif /* EUC */
514		} else if (k >= nchtab + _SPECCHAR_ST) {
515			oput(k - nchtab - _SPECCHAR_ST);
516		} else {
517			int oj = j;
518			codep = t.codetab[k-_SPECCHAR_ST];
519			while (*codep != 0) {
520				if (*codep & 0200) {
521					codep = plot(codep);
522					oput(' ');
523				} else {
524					if (*codep == '%')	/* escape */
525						codep++;
526					oput(*codep);
527					if (*codep == '\033')
528						oput(*++codep);
529					else if (*codep != '\b')
530						for (j = oj; --j > 0; ) {
531							oput('\b');
532							oput(*codep);
533						}
534					codep++;
535				}
536			}
537		}
538		if (!w)
539			for (j = phyw / t.Char; j > 0; j--)
540				oput('\b');
541	}
542
543	return (0);
544}
545
546
547char	*plot(x)
548char	*x;
549{
550	int	i;
551	char	*j, *k;
552
553	oputs(t.ploton);
554	k = x;
555	if ((*k & 0377) == 0200)
556		k++;
557	for (; *k; k++) {
558		if (*k == '%') {	/* quote char within plot mode */
559			oput(*++k);
560		} else if (*k & 0200) {
561			if (*k & 0100) {
562				if (*k & 040)
563					j = t.up;
564				else
565					j = t.down;
566			} else {
567				if (*k & 040)
568					j = t.left;
569				else
570					j = t.right;
571			}
572			if ((i = *k & 037) == 0) {	/* 2nd 0200 turns it off */
573				++k;
574				break;
575			}
576			while (i--)
577				oputs(j);
578		} else
579			oput(*k);
580	}
581	oputs(t.plotoff);
582	return(k);
583}
584
585
586int
587move()
588{
589	int	k;
590	char	*i, *j;
591	char	*p, *q;
592	int	iesct, dt;
593
594	iesct = esct;
595	if (esct += esc)
596		i = "\0";
597	else
598		i = "\n\0";
599	j = t.hlf;
600	p = t.right;
601	q = t.down;
602	if (lead) {
603		if (lead < 0) {
604			lead = -lead;
605			i = t.flr;
606			/*	if(!esct)i = t.flr; else i = "\0";*/
607			j = t.hlr;
608			q = t.up;
609		}
610		if (*i & 0377) {
611			k = lead / t.Newline;
612			lead = lead % t.Newline;
613			while (k--)
614				oputs(i);
615		}
616		if (*j & 0377) {
617			k = lead / t.Halfline;
618			lead = lead % t.Halfline;
619			while (k--)
620				oputs(j);
621		} else { /* no half-line forward, not at line begining */
622			k = lead / t.Newline;
623			lead = lead % t.Newline;
624			if (k > 0)
625				esc = esct;
626			i = "\n";
627			while (k--)
628				oputs(i);
629		}
630	}
631	if (esc) {
632		if (esc < 0) {
633			esc = -esc;
634			j = "\b";
635			p = t.left;
636		} else {
637			j = " ";
638			if (hflg)
639				while ((dt = dtab - (iesct % dtab)) <= esc) {
640					if (dt % t.Em)
641						break;
642					oput(TAB);
643					esc -= dt;
644					iesct += dt;
645				}
646		}
647		k = esc / t.Em;
648		esc = esc % t.Em;
649		while (k--)
650			oputs(j);
651	}
652	if ((*t.ploton & 0377) && (esc || lead)) {
653		oputs(t.ploton);
654		esc /= t.Hor;
655		lead /= t.Vert;
656		while (esc--)
657			oputs(p);
658		while (lead--)
659			oputs(q);
660		oputs(t.plotoff);
661	}
662	esc = lead = 0;
663
664	return (0);
665}
666
667
668int
669ptlead()
670{
671	move();
672
673	return (0);
674}
675
676
677int
678dostop()
679{
680	char	junk;
681
682	flusho();
683	read(2, &junk, 1);
684
685	return (0);
686}
687
688int
689newpage()
690{
691	return (0);
692}
693
694
695int
696pttrailer()
697{
698	return (0);
699}
700