xref: /illumos-gate/usr/src/cmd/troff/nroff.d/n10.c (revision 0dee7919e2f2a6479d16b370af93747b9416b242)
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 /*
43 n10.c
44 
45 Device 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 
61 struct t t;	/* terminal characteristics */
62 
63 int	dtab;
64 int	plotmode;
65 int	esct;
66 
67 char	xchname[4 * (NROFFCHARS-_SPECCHAR_ST)];	/* hy, em, etc. */
68 short	xchtab[NROFFCHARS-_SPECCHAR_ST];		/* indexes into chname[] */
69 char	*codestr;
70 char	*chname = xchname;
71 short	*chtab = xchtab;
72 int	nchtab = 0;
73 
74 
75 int	Inch;
76 int	Hor;
77 int	Vert;
78 int	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 
85 int	c_hyphen;
86 int	c_emdash;
87 int	c_rule;
88 int	c_minus;
89 int	c_fi;
90 int	c_fl;
91 int	c_ff;
92 int	c_ffi;
93 int	c_ffl;
94 int	c_acute;
95 int	c_grave;
96 int	c_under;
97 int	c_rooten;
98 int	c_boxrule;
99 int	c_lefthand;
100 int	c_dagger;
101 int	c_isalnum;
102 
103 int
104 ptinit()
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 
208 char *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 
219 char *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 
266 char *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 
281 int
282 specnames()
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 
317 int
318 findch(s)	/* find char s in chname */
319 char	*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 
329 int
330 twdone()
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 
348 int
349 ptout(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 
377 int
378 ptout1()
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 
547 char	*plot(x)
548 char	*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 
586 int
587 move()
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 
668 int
669 ptlead()
670 {
671 	move();
672 
673 	return (0);
674 }
675 
676 
677 int
678 dostop()
679 {
680 	char	junk;
681 
682 	flusho();
683 	read(2, &junk, 1);
684 
685 	return (0);
686 }
687 
688 int
689 newpage()
690 {
691 	return (0);
692 }
693 
694 
695 int
696 pttrailer()
697 {
698 	return (0);
699 }
700