xref: /titanic_44/usr/src/cmd/troff/nroff.d/n10.c (revision b7f45089ccbe01bab3d7c7377b49d80d2ae18a69)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * University Copyright- Copyright (c) 1982, 1986, 1988
35  * The Regents of the University of California
36  * All Rights Reserved
37  *
38  * University Acknowledgment- Portions of this document are derived from
39  * software developed by the University of California, Berkeley, and its
40  * contributors.
41  */
42 
43 /*
44 n10.c
45 
46 Device interfaces
47 */
48 
49 #include <limits.h>
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #ifdef EUC
54 #ifdef NROFF
55 #include <stdlib.h>
56 #endif /* NROFF */
57 #endif /* EUC */
58 #include "tdef.h"
59 #include "ext.h"
60 #include "tw.h"
61 
62 struct t t;	/* terminal characteristics */
63 
64 int	dtab;
65 int	plotmode;
66 int	esct;
67 
68 char	xchname[4 * (NROFFCHARS-_SPECCHAR_ST)];	/* hy, em, etc. */
69 short	xchtab[NROFFCHARS-_SPECCHAR_ST];		/* indexes into chname[] */
70 char	*codestr;
71 char	*chname = xchname;
72 short	*chtab = xchtab;
73 int	nchtab = 0;
74 
75 
76 int	Inch;
77 int	Hor;
78 int	Vert;
79 int	nfonts	= 4;	/* R, I, B, S */
80 
81 /* these characters are used as various signals or values
82  * in miscellaneous places.
83  * values are set in specnames in t10.c
84  */
85 
86 int	c_hyphen;
87 int	c_emdash;
88 int	c_rule;
89 int	c_minus;
90 int	c_fi;
91 int	c_fl;
92 int	c_ff;
93 int	c_ffi;
94 int	c_ffl;
95 int	c_acute;
96 int	c_grave;
97 int	c_under;
98 int	c_rooten;
99 int	c_boxrule;
100 int	c_lefthand;
101 int	c_dagger;
102 int	c_isalnum;
103 
104 ptinit()
105 {
106 	register int i, j;
107 	register 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 
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 
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 
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 specnames()
280 {
281 	static struct {
282 		int	*n;
283 		char	*v;
284 	} spnames[] = {
285 		&c_hyphen, "hy",
286 		&c_emdash, "em",
287 		&c_rule, "ru",
288 		&c_minus, "\\-",
289 		&c_fi, "fi",
290 		&c_fl, "fl",
291 		&c_ff, "ff",
292 		&c_ffi, "Fi",
293 		&c_ffl, "Fl",
294 		&c_acute, "aa",
295 		&c_grave, "ga",
296 		&c_under, "ul",
297 		&c_rooten, "rn",
298 		&c_boxrule, "br",
299 		&c_lefthand, "lh",
300 		&c_isalnum, "__",
301 		0, 0
302 	};
303 	int	i;
304 
305 	for (i = 0; spnames[i].n; i++)
306 		*spnames[i].n = findch(spnames[i].v);
307 	if (c_isalnum == 0)
308 		c_isalnum = NROFFCHARS;
309 }
310 
311 
312 findch(s)	/* find char s in chname */
313 register char	*s;
314 {
315 	register int	i;
316 
317 	for (i = 0; chtab[i] != 0; i++)
318 		if (strcmp(s, &chname[chtab[i]]) == 0)
319 			return(i + _SPECCHAR_ST);
320 	return(0);
321 }
322 
323 twdone()
324 {
325 	int waitf;
326 
327 	obufp = obuf;
328 	if (t.twrest)		/* has ptinit() been done yet? */
329 		oputs(t.twrest);
330 	flusho();
331 	if (pipeflg) {
332 		close(ptid);
333 		wait(&waitf);
334 	}
335 	restore_tty();
336 }
337 
338 
339 ptout(i)
340 	tchar i;
341 {
342 	*olinep++ = i;
343 	if (olinep >= &oline[LNSIZE])
344 		olinep--;
345 	if (cbits(i) != '\n')
346 		return;
347 	olinep--;
348 	lead += dip->blss + lss - t.Newline;
349 	dip->blss = 0;
350 	esct = esc = 0;
351 	if (olinep > oline) {
352 		move();
353 		ptout1();
354 		oputs(t.twnl);
355 	} else {
356 		lead += t.Newline;
357 		move();
358 	}
359 	lead += dip->alss;
360 	dip->alss = 0;
361 	olinep = oline;
362 }
363 
364 
365 ptout1()
366 {
367 	register k;
368 	register char	*codep;
369 #ifdef EUC
370 #ifdef NROFF
371 	register int cnt;
372 	register tchar *qq;
373 #endif /* NROFF */
374 #endif /* EUC */
375 	extern char	*plot();
376 	int	w, j, phyw;
377 #ifdef EUC
378 #ifdef NROFF
379 	int jj;
380 #endif /* NROFF */
381 #endif /* EUC */
382 	tchar * q, i;
383 	static int oxfont = FT;	/* start off in roman */
384 
385 	for (q = oline; q < olinep; q++) {
386 		i = *q;
387 		if (ismot(i)) {
388 			j = absmot(i);
389 			if (isnmot(i))
390 				j = -j;
391 			if (isvmot(i))
392 				lead += j;
393 			else
394 				esc += j;
395 			continue;
396 		}
397 		if ((k = cbits(i)) <= 040) {
398 			switch (k) {
399 			case ' ': /*space*/
400 				esc += t.Char;
401 				break;
402 			case '\033':
403 			case '\007':
404 			case '\016':
405 			case '\017':
406 				oput(k);
407 				break;
408 			}
409 			continue;
410 		}
411 #ifdef EUC
412 #ifdef NROFF
413 		if (multi_locale && ((k & MBMASK) || (k & CSMASK))) {
414 			cnt = 0;
415 			while ((*q & MBMASK1) && (cnt + 1 < (int)MB_CUR_MAX)) {
416 				cnt++;
417 				q++;
418 			}
419 			if ((cnt && !(*q & CSMASK)) || (*q & MBMASK1)) {
420 				q -= cnt;
421 				cnt = 0;
422 				*q &= ~0xfe00;
423 			}
424 			k = cbits(i = *q);
425 			phyw = w = t.Char * csi_width[cs(i)];
426 		} else {
427 #endif /* NROFF */
428 #endif /* EUC */
429 		phyw = w = t.Char * t.width[k];
430 		if (iszbit(i))
431 			w = 0;
432 #ifdef EUC
433 #ifdef NROFF
434 		}
435 #endif /* NROFF */
436 #endif /* EUC */
437 		if (esc || lead)
438 			move();
439 		esct += w;
440 #ifndef EUC
441 		xfont = fbits(i);
442 #else
443 #ifndef NROFF
444 		xfont = fbits(i);
445 #else
446 #endif /* NROFF */
447 		xfont = (fbits(*q) % NFONT);	/* for invalid code */
448 #endif /* EUC */
449 		if (xfont != oxfont) {
450 			if (oxfont == ulfont || oxfont == BIFONT)
451 				oputs(t.itoff);
452 			if (bdtab[oxfont])
453 				oputs(t.bdoff);
454 			if (xfont == ulfont || xfont == BIFONT)
455 				oputs(t.iton);
456 			if (bdtab[xfont])
457 				oputs(t.bdon);
458 			oxfont = xfont;
459 		}
460 		if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) {
461 			for (j = w / t.Char; j > 0; j--)
462 				oput('_');
463 			for (j = w / t.Char; j > 0; j--)
464 				oput('\b');
465 		}
466 		if ((j = bdtab[xfont]) && !(*t.bdon & 0377))
467 			j++;
468 		else
469 			j = 1;	/* number of overstrikes for bold */
470 		if (k < 128) {	/* ordinary ascii */
471 			oput(k);
472 			while (--j > 0) {
473 				oput('\b');
474 				oput(k);
475 			}
476 #ifdef EUC
477 #ifdef NROFF
478 		} else if (multi_locale && (k & CSMASK)) {
479 			for (qq = q - cnt; qq <= q;)
480 				oput(cbits(*qq++));
481 			while (--j > 0) {
482 				for (jj = cnt + 1; jj > 0; jj--)
483 					oput('\b');
484 				for (qq = q - cnt; qq <= q;)
485 					oput(cbits(*qq++));
486 			}
487 		} else if (k < 256) {
488 			/*
489 			 * Invalid character for C locale or
490 			 * non-printable 8-bit single byte
491 			 * character such as <no-break-sp>
492 			 * in ISO-8859-1
493 			 */
494 			oput(k);
495 			while (--j > 0) {
496 				oput('\b');
497 				oput(k);
498 			}
499 #endif /* NROFF */
500 #endif /* EUC */
501 		} else if (k >= nchtab + _SPECCHAR_ST) {
502 			oput(k - nchtab - _SPECCHAR_ST);
503 		} else {
504 			int oj = j;
505 			codep = t.codetab[k-_SPECCHAR_ST];
506 			while (*codep != 0) {
507 				if (*codep & 0200) {
508 					codep = plot(codep);
509 					oput(' ');
510 				} else {
511 					if (*codep == '%')	/* escape */
512 						codep++;
513 					oput(*codep);
514 					if (*codep == '\033')
515 						oput(*++codep);
516 					else if (*codep != '\b')
517 						for (j = oj; --j > 0; ) {
518 							oput('\b');
519 							oput(*codep);
520 						}
521 					codep++;
522 				}
523 			}
524 		}
525 		if (!w)
526 			for (j = phyw / t.Char; j > 0; j--)
527 				oput('\b');
528 	}
529 }
530 
531 
532 char	*plot(x)
533 char	*x;
534 {
535 	register int	i;
536 	register char	*j, *k;
537 
538 	oputs(t.ploton);
539 	k = x;
540 	if ((*k & 0377) == 0200)
541 		k++;
542 	for (; *k; k++) {
543 		if (*k == '%') {	/* quote char within plot mode */
544 			oput(*++k);
545 		} else if (*k & 0200) {
546 			if (*k & 0100) {
547 				if (*k & 040)
548 					j = t.up;
549 				else
550 					j = t.down;
551 			} else {
552 				if (*k & 040)
553 					j = t.left;
554 				else
555 					j = t.right;
556 			}
557 			if ((i = *k & 037) == 0) {	/* 2nd 0200 turns it off */
558 				++k;
559 				break;
560 			}
561 			while (i--)
562 				oputs(j);
563 		} else
564 			oput(*k);
565 	}
566 	oputs(t.plotoff);
567 	return(k);
568 }
569 
570 
571 move()
572 {
573 	register k;
574 	register char	*i, *j;
575 	char	*p, *q;
576 	int	iesct, dt;
577 
578 	iesct = esct;
579 	if (esct += esc)
580 		i = "\0";
581 	else
582 		i = "\n\0";
583 	j = t.hlf;
584 	p = t.right;
585 	q = t.down;
586 	if (lead) {
587 		if (lead < 0) {
588 			lead = -lead;
589 			i = t.flr;
590 			/*	if(!esct)i = t.flr; else i = "\0";*/
591 			j = t.hlr;
592 			q = t.up;
593 		}
594 		if (*i & 0377) {
595 			k = lead / t.Newline;
596 			lead = lead % t.Newline;
597 			while (k--)
598 				oputs(i);
599 		}
600 		if (*j & 0377) {
601 			k = lead / t.Halfline;
602 			lead = lead % t.Halfline;
603 			while (k--)
604 				oputs(j);
605 		} else { /* no half-line forward, not at line begining */
606 			k = lead / t.Newline;
607 			lead = lead % t.Newline;
608 			if (k > 0)
609 				esc = esct;
610 			i = "\n";
611 			while (k--)
612 				oputs(i);
613 		}
614 	}
615 	if (esc) {
616 		if (esc < 0) {
617 			esc = -esc;
618 			j = "\b";
619 			p = t.left;
620 		} else {
621 			j = " ";
622 			if (hflg)
623 				while ((dt = dtab - (iesct % dtab)) <= esc) {
624 					if (dt % t.Em)
625 						break;
626 					oput(TAB);
627 					esc -= dt;
628 					iesct += dt;
629 				}
630 		}
631 		k = esc / t.Em;
632 		esc = esc % t.Em;
633 		while (k--)
634 			oputs(j);
635 	}
636 	if ((*t.ploton & 0377) && (esc || lead)) {
637 		oputs(t.ploton);
638 		esc /= t.Hor;
639 		lead /= t.Vert;
640 		while (esc--)
641 			oputs(p);
642 		while (lead--)
643 			oputs(q);
644 		oputs(t.plotoff);
645 	}
646 	esc = lead = 0;
647 }
648 
649 
650 ptlead()
651 {
652 	move();
653 }
654 
655 
656 dostop()
657 {
658 	char	junk;
659 
660 	flusho();
661 	read(2, &junk, 1);
662 }
663 
664 
665 newpage(){;}
666 pttrailer(){;}
667