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