1 #ifndef lint
2 /*
3 static char sccsid[]="@(#)n10.c	1.2	(CWI)	86/08/15";
4 */
5 static char sccsid[] = "@(#)n10.c	1.3 (Berkeley) 11/03/90";
6 #endif
7 
8 /*
9 n10.c
10 
11 Device interfaces
12 */
13 
14 #include "tdef.h"
15 #include "ext.h"
16 #include "tw.h"
17 #include <sgtty.h>
18 #include <ctype.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 
22 struct t t;	/* terminal characteristics */
23 
24 int	dtab;
25 int	plotmode;
26 int	esct;
27 
28 char	xchname[4 * (NROFFCHARS-128)];	/* hy, em, etc. */
29 short	xchtab[NROFFCHARS-128];		/* indexes into chname[] */
30 char	*codestr;
31 char	*chname = xchname;
32 short	*chtab = xchtab;
33 
34 
35 int	Inch;
36 int	Hor;
37 int	Vert;
38 int	nfonts	= 4;	/* R, I, B, S */
39 
40 /* these characters are used as various signals or values
41 /* in miscellaneous places.
42 /* values are set in specnames in t10.c
43 */
44 
45 int	c_hyphen;
46 int	c_emdash;
47 int	c_rule;
48 int	c_minus;
49 int	c_fi;
50 int	c_fl;
51 int	c_ff;
52 int	c_ffi;
53 int	c_ffl;
54 int	c_acute;
55 int	c_grave;
56 int	c_under;
57 int	c_rooten;
58 int	c_boxrule;
59 int	c_lefthand;
60 int	c_dagger;
61 int	c_isalnum;
62 
63 ptinit()
64 {
65 	register int i, j;
66 	register char *p, *cp, *q;
67 	int nread, fd;
68 	extern char *skipstr(), *getstr(), *getint();
69 	struct stat stbuf;
70 	char check[50];
71 
72 	strcat(termtab, devname);
73 	if ((fd = open(termtab, 0)) < 0) {
74 		errprint("cannot open %s", termtab);
75 		exit(-1);
76 	}
77 
78 	fstat(fd, &stbuf);
79 	codestr = malloc((int) stbuf.st_size);
80 
81 	nread = read(fd, codestr, (int) stbuf.st_size);
82 	close(fd);
83 
84 	p = codestr;
85 	p = skipstr(p);		/* skip over type, could check */
86 	p = skipstr(p); p = getint(p, &t.bset);
87 	p = skipstr(p); p = getint(p, &t.breset);
88 	p = skipstr(p); p = getint(p, &t.Hor);
89 	p = skipstr(p); p = getint(p, &t.Vert);
90 	p = skipstr(p); p = getint(p, &t.Newline);
91 	p = skipstr(p); p = getint(p, &t.Char);
92 	p = skipstr(p); p = getint(p, &t.Em);
93 	p = skipstr(p); p = getint(p, &t.Halfline);
94 	p = skipstr(p); p = getint(p, &t.Adj);
95 	p = skipstr(p); p = getstr(p, t.twinit = p);
96 	p = skipstr(p); p = getstr(p, t.twrest = p);
97 	p = skipstr(p); p = getstr(p, t.twnl = p);
98 	p = skipstr(p); p = getstr(p, t.hlr = p);
99 	p = skipstr(p); p = getstr(p, t.hlf = p);
100 	p = skipstr(p); p = getstr(p, t.flr = p);
101 	p = skipstr(p); p = getstr(p, t.bdon = p);
102 	p = skipstr(p); p = getstr(p, t.bdoff = p);
103 	p = skipstr(p); p = getstr(p, t.iton = p);
104 	p = skipstr(p); p = getstr(p, t.itoff = p);
105 	p = skipstr(p); p = getstr(p, t.ploton = p);
106 	p = skipstr(p); p = getstr(p, t.plotoff = p);
107 	p = skipstr(p); p = getstr(p, t.up = p);
108 	p = skipstr(p); p = getstr(p, t.down = p);
109 	p = skipstr(p); p = getstr(p, t.right = p);
110 	p = skipstr(p); p = getstr(p, t.left = p);
111 	p = skipstr(p); p = getstr(p, t.eject = p);
112 
113 	getstr(p, check);
114 	if (strcmp(check, "charset") != 0) {
115 		errprint("device table apparently curdled");
116 		exit(1);
117 	}
118 
119 	for (i = 0; i < 128; i++)
120 		t.width[i] = 1;	/* default ascii widths */
121 
122 	i = 0;
123 /* this ought to be a pointer array and in place in codestr */
124 	cp = chname + 1;	/* bug if starts at 0, in setch */
125 	while (p < codestr + nread) {
126 		while (*p == ' ' || *p == '\t' || *p == '\n')
127 			p++;
128 		chtab[i] = cp - chname;	/* index, not pointer */
129 		*cp++ = *p++;	/* 2-char names */
130 		*cp++ = *p++;
131 		*cp++ = '\0';
132 		while (*p == ' ' || *p == '\t')
133 			p++;
134 		t.width[i+128] = *p++ - '0';
135 		while (*p == ' ' || *p == '\t')
136 			p++;
137 		t.codetab[i] = p;
138 		p = getstr(p, p);	/* compress string */
139 		p++;
140 		i++;
141 	}
142 
143 	sps = EM;
144 	ics = EM * 2;
145 	dtab = 8 * t.Em;
146 	for (i = 0; i < 16; i++)
147 		tabtab[i] = dtab * (i + 1);
148 	pl = 11 * INCH;
149 	po = PO;
150 	spacesz = SS;
151 	lss = lss1 = VS;
152 	ll = ll1 = lt = lt1 = LL;
153 	smnt = nfonts = 5;	/* R I B BI S */
154 	specnames();	/* install names like "hyphen", etc. */
155 	if (eqflg)
156 		t.Adj = t.Hor;
157 }
158 
159 char *skipstr(s)	/* skip over leading space plus string */
160 	char *s;
161 {
162 	while (*s == ' ' || *s == '\t' || *s == '\n')
163 		s++;
164 	while (*s != ' ' && *s != '\t' && *s != '\n')
165 		if (*s++ == '\\')
166 			s++;
167 	return s;
168 }
169 
170 char *getstr(s, t)	/* find next string in s, copy to t */
171 	char *s, *t;
172 {
173 	int quote = 0;
174 
175 	while (*s == ' ' || *s == '\t' || *s == '\n')
176 		s++;
177 	if (*s == '"') {
178 		s++;
179 		quote = 1;
180 	}
181 	for (;;) {
182 		if (quote && *s == '"') {
183 			s++;
184 			break;
185 		}
186 		if (!quote && (*s == ' ' || *s == '\t' || *s == '\n'))
187 			break;
188 		if (*s != '\\')
189 			*t++ = *s++;
190 		else {
191 			s++;	/* skip \\ */
192 			if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) {
193 				*t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0';
194 				s += 2;
195 			} else if (isdigit(s[0])) {
196 				*t++ = *s - '0';
197 			} else if (*s == 'b') {
198 				*t++ = '\b';
199 			} else if (*s == 'n') {
200 				*t++ = '\n';
201 			} else if (*s == 'r') {
202 				*t++ = '\r';
203 			} else if (*s == 't') {
204 				*t++ = '\t';
205 			} else {
206 				*t++ = *s;
207 			}
208 			s++;
209 		}
210 	}
211 	*t = '\0';
212 	return s;
213 }
214 
215 char *getint(s, pn)	/* find integer at s */
216 	char *s;
217 	int *pn;
218 {
219 	while (*s == ' ' || *s == '\t' || *s == '\n')
220 		s++;
221 	*pn = 0;
222 	while (isdigit(*s))
223 		*pn = 10 * *pn + *s++ - '0';
224 	return s;
225 }
226 
227 specnames()
228 {
229 	static struct {
230 		int	*n;
231 		char	*v;
232 	} spnames[] = {
233 		&c_hyphen, "hy",
234 		&c_emdash, "em",
235 		&c_rule, "ru",
236 		&c_minus, "\\-",
237 		&c_fi, "fi",
238 		&c_fl, "fl",
239 		&c_ff, "ff",
240 		&c_ffi, "Fi",
241 		&c_ffl, "Fl",
242 		&c_acute, "aa",
243 		&c_grave, "ga",
244 		&c_under, "ul",
245 		&c_rooten, "rn",
246 		&c_boxrule, "br",
247 		&c_lefthand, "lh",
248 		&c_isalnum, "__",
249 		0, 0
250 	};
251 	int	i;
252 
253 	for (i = 0; spnames[i].n; i++)
254 		*spnames[i].n = findch(spnames[i].v);
255 	if (c_isalnum == 0)
256 		c_isalnum = NROFFCHARS;
257 }
258 
259 
260 findch(s)	/* find char s in chname */
261 register char	*s;
262 {
263 	register int	i;
264 
265 	for (i = 0; chtab[i] != 0; i++)
266 		if (strcmp(s, &chname[chtab[i]]) == 0)
267 			return(i + 128);
268 	return(0);
269 }
270 
271 twdone()
272 {
273 	int waitf;
274 
275 	oputs(t.twrest);
276 	flusho();
277 	if (pipeflg) {
278 		close(fileno(ptid));
279 		wait(&waitf);
280 	}
281 	if (ttysave != -1) {
282 		ttys.sg_flags = ttysave;
283 		stty(1, &ttys);
284 	}
285 }
286 
287 
288 ptout(i)
289 	tchar i;
290 {
291 	*olinep++ = i;
292 	if (olinep >= &oline[LNSIZE])
293 		olinep--;
294 	if (cbits(i) != '\n')
295 		return;
296 	olinep--;
297 	lead += dip->blss + lss - t.Newline;
298 	dip->blss = 0;
299 	esct = esc = 0;
300 	if (olinep > oline) {
301 		move();
302 		ptout1();
303 		oputs(t.twnl);
304 	} else {
305 		lead += t.Newline;
306 		move();
307 	}
308 	lead += dip->alss;
309 	dip->alss = 0;
310 	olinep = oline;
311 }
312 
313 
314 ptout1()
315 {
316 	register k;
317 	register char	*codep;
318 	extern char	*plot();
319 	int	w, j, phyw;
320 	tchar * q, i;
321 	static int oxfont = FT;	/* start off in roman */
322 
323 	for (q = oline; q < olinep; q++) {
324 		i = *q;
325 		if (ismot(i)) {
326 			j = absmot(i);
327 			if (isnmot(i))
328 				j = -j;
329 			if (isvmot(i))
330 				lead += j;
331 			else
332 				esc += j;
333 			continue;
334 		}
335 		if ((k = cbits(i)) <= 040) {
336 			switch (k) {
337 			case ' ': /*space*/
338 				esc += t.Char;
339 				break;
340 			case '\033':
341 			case '\007':
342 			case '\016':
343 			case '\017':
344 				oput(k);
345 				break;
346 			}
347 			continue;
348 		}
349 		phyw = w = t.Char * t.width[k];
350 		if (iszbit(i))
351 			w = 0;
352 		if (esc || lead)
353 			move();
354 		esct += w;
355 		xfont = fbits(i);
356 		if (xfont != oxfont) {
357 			switch (oxfont) {
358 			case ULFONT:	oputs(t.itoff); break;
359 			case BDFONT:	oputs(t.bdoff); break;
360 			case BIFONT:	oputs(t.itoff); oputs(t.bdoff); break;
361 			}
362 			switch (xfont) {
363 			case ULFONT:
364 				if (*t.iton & 0377) oputs(t.iton); break;
365 			case BDFONT:
366 				if (*t.bdon & 0377) oputs(t.bdon); break;
367 			case BIFONT:
368 				if (*t.bdon & 0377) oputs(t.bdon);
369 				if (*t.iton & 0377) oputs(t.iton);
370 				break;
371 			}
372 			oxfont = xfont;
373 		}
374 		if ((xfont == ULFONT || xfont == BIFONT) && !(*t.iton & 0377)) {
375 			for (j = w / t.Char; j > 0; j--)
376 				oput('_');
377 			for (j = w / t.Char; j > 0; j--)
378 				oput('\b');
379 		}
380 		if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT))
381 			j++;
382 		else
383 			j = 1;	/* number of overstrikes for bold */
384 		if (k < 128) {	/* ordinary ascii */
385 			oput(k);
386 			while (--j > 0) {
387 				oput('\b');
388 				oput(k);
389 			}
390 		} else {
391 			int oj = j;
392 			codep = t.codetab[k-128];
393 			while (*codep != 0) {
394 				if (*codep & 0200) {
395 					codep = plot(codep);
396 					oput(' ');
397 				} else {
398 					if (*codep == '%')	/* escape */
399 						codep++;
400 					oput(*codep);
401 					if (*codep != '\b')
402 						for (j = oj; --j > 0; ) {
403 							oput('\b');
404 							oput(*codep);
405 						}
406 					codep++;
407 				}
408 			}
409 		}
410 		if (!w)
411 			for (j = phyw / t.Char; j > 0; j--)
412 				oput('\b');
413 	}
414 }
415 
416 
417 char	*plot(x)
418 char	*x;
419 {
420 	register int	i;
421 	register char	*j, *k;
422 
423 	oputs(t.ploton);
424 	k = x;
425 	if ((*k & 0377) == 0200)
426 		k++;
427 	for (; *k; k++) {
428 		if (*k == '%') {	/* quote char within plot mode */
429 			oput(*++k);
430 		} else if (*k & 0200) {
431 			if (*k & 0100) {
432 				if (*k & 040)
433 					j = t.up;
434 				else
435 					j = t.down;
436 			} else {
437 				if (*k & 040)
438 					j = t.left;
439 				else
440 					j = t.right;
441 			}
442 			if ((i = *k & 037) == 0) {	/* 2nd 0200 turns it off */
443 				++k;
444 				break;
445 			}
446 			while (i--)
447 				oputs(j);
448 		} else
449 			oput(*k);
450 	}
451 	oputs(t.plotoff);
452 	return(k);
453 }
454 
455 
456 move()
457 {
458 	register k;
459 	register char	*i, *j;
460 	char	*p, *q;
461 	int	iesct, dt;
462 
463 	iesct = esct;
464 	if (esct += esc)
465 		i = "\0";
466 	else
467 		i = "\n\0";
468 	j = t.hlf;
469 	p = t.right;
470 	q = t.down;
471 	if (lead) {
472 		if (lead < 0) {
473 			lead = -lead;
474 			i = t.flr;
475 			/*	if(!esct)i = t.flr; else i = "\0";*/
476 			j = t.hlr;
477 			q = t.up;
478 		}
479 		if (*i & 0377) {
480 			k = lead / t.Newline;
481 			lead = lead % t.Newline;
482 			while (k--)
483 				oputs(i);
484 		}
485 		if (*j & 0377) {
486 			k = lead / t.Halfline;
487 			lead = lead % t.Halfline;
488 			while (k--)
489 				oputs(j);
490 		} else { /* no half-line forward, not at line begining */
491 			k = lead / t.Newline;
492 			lead = lead % t.Newline;
493 			if (k > 0)
494 				esc = esct;
495 			i = "\n";
496 			while (k--)
497 				oputs(i);
498 		}
499 	}
500 	if (esc) {
501 		if (esc < 0) {
502 			esc = -esc;
503 			j = "\b";
504 			p = t.left;
505 		} else {
506 			j = " ";
507 			if (hflg)
508 				while ((dt = dtab - (iesct % dtab)) <= esc) {
509 					if (dt % t.Em)
510 						break;
511 					oput(TAB);
512 					esc -= dt;
513 					iesct += dt;
514 				}
515 		}
516 		k = esc / t.Em;
517 		esc = esc % t.Em;
518 		while (k--)
519 			oputs(j);
520 	}
521 	if ((*t.ploton & 0377) && (esc || lead)) {
522 		oputs(t.ploton);
523 		esc /= t.Hor;
524 		lead /= t.Vert;
525 		while (esc--)
526 			oputs(p);
527 		while (lead--)
528 			oputs(q);
529 		oputs(t.plotoff);
530 	}
531 	esc = lead = 0;
532 }
533 
534 
535 ptlead()
536 {
537 	move();
538 }
539 
540 
541 dostop()
542 {
543 	char	junk;
544 
545 	flusho();
546 	read(2, &junk, 1);
547 }
548 
549 
550 newpage(){;}
551 pttrailer(){;}
552